xref: /netbsd-src/external/gpl3/binutils.old/dist/libctf/ctf-lookup.c (revision c42dbd0ed2e61fe6eda8590caa852ccf34719964)
1 /* Symbol, variable and name lookup.
2    Copyright (C) 2019-2022 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
grow_pptrtab(ctf_dict_t * fp,size_t new_len)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
refresh_pptrtab(ctf_dict_t * fp,ctf_dict_t * pfp)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
isqualifier(const char * s,size_t len)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
ctf_lookup_by_name_internal(ctf_dict_t * fp,ctf_dict_t * child,const char * name)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_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 		    {
277 		      ctf_set_errno (fp, ENOMEM);
278 		      return CTF_ERR;
279 		    }
280 		}
281 
282 	      if ((type = ctf_lookup_by_rawhash (fp, lp->ctl_hash,
283 						 fp->ctf_tmp_typeslice)) == 0)
284 		goto notype;
285 
286 	      break;
287 	    }
288 	}
289 
290       if (lp->ctl_prefix == NULL)
291 	goto notype;
292     }
293 
294   if (*p != '\0' || type == 0)
295     return (ctf_set_errno (fp, ECTF_SYNTAX));
296 
297   return type;
298 
299  notype:
300   ctf_set_errno (fp, ECTF_NOTYPE);
301   if (fp->ctf_parent != NULL)
302     {
303       /* Need to look up in the parent, from the child's perspective.
304 	 Make sure the pptrtab is up to date.  */
305 
306       if (fp->ctf_pptrtab_typemax < fp->ctf_typemax)
307 	{
308 	  if (refresh_pptrtab (fp, fp->ctf_parent) < 0)
309 	    return -1;			/* errno is set for us.  */
310 	}
311 
312       if ((ptype = ctf_lookup_by_name_internal (fp->ctf_parent, fp,
313 						name)) != CTF_ERR)
314 	return ptype;
315       return (ctf_set_errno (fp, ctf_errno (fp->ctf_parent)));
316     }
317 
318   return CTF_ERR;
319 }
320 
321 ctf_id_t
ctf_lookup_by_name(ctf_dict_t * fp,const char * name)322 ctf_lookup_by_name (ctf_dict_t *fp, const char *name)
323 {
324   return ctf_lookup_by_name_internal (fp, NULL, name);
325 }
326 
327 /* Return the pointer to the internal CTF type data corresponding to the
328    given type ID.  If the ID is invalid, the function returns NULL.
329    This function is not exported outside of the library.  */
330 
331 const ctf_type_t *
ctf_lookup_by_id(ctf_dict_t ** fpp,ctf_id_t type)332 ctf_lookup_by_id (ctf_dict_t **fpp, ctf_id_t type)
333 {
334   ctf_dict_t *fp = *fpp;	/* Caller passes in starting CTF dict.  */
335   ctf_id_t idx;
336 
337   if ((fp = ctf_get_dict (fp, type)) == NULL)
338     {
339       (void) ctf_set_errno (*fpp, ECTF_NOPARENT);
340       return NULL;
341     }
342 
343   /* If this dict is writable, check for a dynamic type.  */
344 
345   if (fp->ctf_flags & LCTF_RDWR)
346     {
347       ctf_dtdef_t *dtd;
348 
349       if ((dtd = ctf_dynamic_type (fp, type)) != NULL)
350 	{
351 	  *fpp = fp;
352 	  return &dtd->dtd_data;
353 	}
354       (void) ctf_set_errno (*fpp, ECTF_BADID);
355       return NULL;
356     }
357 
358   /* Check for a type in the static portion.  */
359 
360   idx = LCTF_TYPE_TO_INDEX (fp, type);
361   if (idx > 0 && (unsigned long) idx <= fp->ctf_typemax)
362     {
363       *fpp = fp;		/* Function returns ending CTF dict.  */
364       return (LCTF_INDEX_TO_TYPEPTR (fp, idx));
365     }
366 
367   (void) ctf_set_errno (*fpp, ECTF_BADID);
368   return NULL;
369 }
370 
371 typedef struct ctf_lookup_idx_key
372 {
373   ctf_dict_t *clik_fp;
374   const char *clik_name;
375   uint32_t *clik_names;
376 } ctf_lookup_idx_key_t;
377 
378 /* A bsearch function for variable names.  */
379 
380 static int
ctf_lookup_var(const void * key_,const void * lookup_)381 ctf_lookup_var (const void *key_, const void *lookup_)
382 {
383   const ctf_lookup_idx_key_t *key = key_;
384   const ctf_varent_t *lookup = lookup_;
385 
386   return (strcmp (key->clik_name, ctf_strptr (key->clik_fp, lookup->ctv_name)));
387 }
388 
389 /* Given a variable name, return the type of the variable with that name.  */
390 
391 ctf_id_t
ctf_lookup_variable(ctf_dict_t * fp,const char * name)392 ctf_lookup_variable (ctf_dict_t *fp, const char *name)
393 {
394   ctf_varent_t *ent;
395   ctf_lookup_idx_key_t key = { fp, name, NULL };
396 
397   /* This array is sorted, so we can bsearch for it.  */
398 
399   ent = bsearch (&key, fp->ctf_vars, fp->ctf_nvars, sizeof (ctf_varent_t),
400 		 ctf_lookup_var);
401 
402   if (ent == NULL)
403     {
404       if (fp->ctf_parent != NULL)
405 	return ctf_lookup_variable (fp->ctf_parent, name);
406 
407       return (ctf_set_errno (fp, ECTF_NOTYPEDAT));
408     }
409 
410   return ent->ctv_type;
411 }
412 
413 typedef struct ctf_symidx_sort_arg_cb
414 {
415   ctf_dict_t *fp;
416   uint32_t *names;
417 } ctf_symidx_sort_arg_cb_t;
418 
419 static int
sort_symidx_by_name(const void * one_,const void * two_,void * arg_)420 sort_symidx_by_name (const void *one_, const void *two_, void *arg_)
421 {
422   const uint32_t *one = one_;
423   const uint32_t *two = two_;
424   ctf_symidx_sort_arg_cb_t *arg = arg_;
425 
426   return (strcmp (ctf_strptr (arg->fp, arg->names[*one]),
427 		  ctf_strptr (arg->fp, arg->names[*two])));
428 }
429 
430 /* Sort a symbol index section by name.  Takes a 1:1 mapping of names to the
431    corresponding symbol table.  Returns a lexicographically sorted array of idx
432    indexes (and thus, of indexes into the corresponding func info / data object
433    section).  */
434 
435 static uint32_t *
ctf_symidx_sort(ctf_dict_t * fp,uint32_t * idx,size_t * nidx,size_t len)436 ctf_symidx_sort (ctf_dict_t *fp, uint32_t *idx, size_t *nidx,
437 			 size_t len)
438 {
439   uint32_t *sorted;
440   size_t i;
441 
442   if ((sorted = malloc (len)) == NULL)
443     {
444       ctf_set_errno (fp, ENOMEM);
445       return NULL;
446     }
447 
448   *nidx = len / sizeof (uint32_t);
449   for (i = 0; i < *nidx; i++)
450     sorted[i] = i;
451 
452   if (!(fp->ctf_header->cth_flags & CTF_F_IDXSORTED))
453     {
454       ctf_symidx_sort_arg_cb_t arg = { fp, idx };
455       ctf_dprintf ("Index section unsorted: sorting.");
456       ctf_qsort_r (sorted, *nidx, sizeof (uint32_t), sort_symidx_by_name, &arg);
457       fp->ctf_header->cth_flags |= CTF_F_IDXSORTED;
458     }
459 
460   return sorted;
461 }
462 
463 /* Given a symbol index, return the name of that symbol from the table provided
464    by ctf_link_shuffle_syms, or failing that from the secondary string table, or
465    the null string.  */
466 static const char *
ctf_lookup_symbol_name(ctf_dict_t * fp,unsigned long symidx)467 ctf_lookup_symbol_name (ctf_dict_t *fp, unsigned long symidx)
468 {
469   const ctf_sect_t *sp = &fp->ctf_symtab;
470   ctf_link_sym_t sym;
471   int err;
472 
473   if (fp->ctf_dynsymidx)
474     {
475       err = EINVAL;
476       if (symidx > fp->ctf_dynsymmax)
477 	goto try_parent;
478 
479       ctf_link_sym_t *symp = fp->ctf_dynsymidx[symidx];
480 
481       if (!symp)
482 	goto try_parent;
483 
484       return symp->st_name;
485     }
486 
487   err = ECTF_NOSYMTAB;
488   if (sp->cts_data == NULL)
489     goto try_parent;
490 
491   if (symidx >= fp->ctf_nsyms)
492     goto try_parent;
493 
494   switch (sp->cts_entsize)
495     {
496     case sizeof (Elf64_Sym):
497       {
498 	const Elf64_Sym *symp = (Elf64_Sym *) sp->cts_data + symidx;
499 	ctf_elf64_to_link_sym (fp, &sym, symp, symidx);
500       }
501       break;
502     case sizeof (Elf32_Sym):
503       {
504 	const Elf32_Sym *symp = (Elf32_Sym *) sp->cts_data + symidx;
505 	ctf_elf32_to_link_sym (fp, &sym, symp, symidx);
506       }
507       break;
508     default:
509       ctf_set_errno (fp, ECTF_SYMTAB);
510       return _CTF_NULLSTR;
511     }
512 
513   assert (!sym.st_nameidx_set);
514 
515   return sym.st_name;
516 
517  try_parent:
518   if (fp->ctf_parent)
519     {
520       const char *ret;
521       ret = ctf_lookup_symbol_name (fp->ctf_parent, symidx);
522       if (ret == NULL)
523 	ctf_set_errno (fp, ctf_errno (fp->ctf_parent));
524       return ret;
525     }
526   else
527     {
528       ctf_set_errno (fp, err);
529       return _CTF_NULLSTR;
530     }
531 }
532 
533 /* Given a symbol name, return the index of that symbol, or -1 on error or if
534    not found.  */
535 static unsigned long
ctf_lookup_symbol_idx(ctf_dict_t * fp,const char * symname)536 ctf_lookup_symbol_idx (ctf_dict_t *fp, const char *symname)
537 {
538   const ctf_sect_t *sp = &fp->ctf_symtab;
539   ctf_link_sym_t sym;
540   void *known_idx;
541   int err;
542   ctf_dict_t *cache = fp;
543 
544   if (fp->ctf_dynsyms)
545     {
546       err = EINVAL;
547 
548       ctf_link_sym_t *symp;
549 
550       if ((symp = ctf_dynhash_lookup (fp->ctf_dynsyms, symname)) == NULL)
551 	goto try_parent;
552 
553       return symp->st_symidx;
554     }
555 
556   err = ECTF_NOSYMTAB;
557   if (sp->cts_data == NULL)
558     goto try_parent;
559 
560   /* First, try a hash lookup to see if we have already spotted this symbol
561      during a past iteration: create the hash first if need be.  The lifespan
562      of the strings is equal to the lifespan of the cts_data, so we don't
563      need to strdup them.  If this dict was opened as part of an archive,
564      and this archive has designed a crossdict_cache to cache results that
565      are the same across all dicts in an archive, use it.  */
566 
567   if (fp->ctf_archive && fp->ctf_archive->ctfi_crossdict_cache)
568     cache = fp->ctf_archive->ctfi_crossdict_cache;
569 
570   if (!cache->ctf_symhash)
571     if ((cache->ctf_symhash = ctf_dynhash_create (ctf_hash_string,
572 						  ctf_hash_eq_string,
573 						  NULL, NULL)) == NULL)
574       goto oom;
575 
576   if (ctf_dynhash_lookup_kv (cache->ctf_symhash, symname, NULL, &known_idx))
577     return (unsigned long) (uintptr_t) known_idx;
578 
579   /* Hash lookup unsuccessful: linear search, populating the hashtab for later
580      lookups as we go.  */
581 
582   for (; cache->ctf_symhash_latest < sp->cts_size / sp->cts_entsize;
583        cache->ctf_symhash_latest++)
584     {
585       switch (sp->cts_entsize)
586 	{
587 	case sizeof (Elf64_Sym):
588 	  {
589 	    Elf64_Sym *symp = (Elf64_Sym *) sp->cts_data;
590 	    ctf_elf64_to_link_sym (fp, &sym, &symp[cache->ctf_symhash_latest],
591 				   cache->ctf_symhash_latest);
592 	    if (!ctf_dynhash_lookup_kv (cache->ctf_symhash, sym.st_name,
593 					NULL, NULL))
594 	      if (ctf_dynhash_cinsert (cache->ctf_symhash, sym.st_name,
595 				       (const void *) (uintptr_t)
596 				       cache->ctf_symhash_latest) < 0)
597 		goto oom;
598 	    if (strcmp (sym.st_name, symname) == 0)
599 	      return cache->ctf_symhash_latest++;
600 	  }
601 	  break;
602 	case sizeof (Elf32_Sym):
603 	  {
604 	    Elf32_Sym *symp = (Elf32_Sym *) sp->cts_data;
605 	    ctf_elf32_to_link_sym (fp, &sym, &symp[cache->ctf_symhash_latest],
606 				   cache->ctf_symhash_latest);
607 	    if (!ctf_dynhash_lookup_kv (cache->ctf_symhash, sym.st_name,
608 					NULL, NULL))
609 	      if (ctf_dynhash_cinsert (cache->ctf_symhash, sym.st_name,
610 				       (const void *) (uintptr_t)
611 				       cache->ctf_symhash_latest) < 0)
612 		goto oom;
613 	    if (strcmp (sym.st_name, symname) == 0)
614 	      return cache->ctf_symhash_latest++;
615 	  }
616 	  break;
617 	default:
618 	  ctf_set_errno (fp, ECTF_SYMTAB);
619 	  return (unsigned long) -1;
620 	}
621     }
622 
623   /* Searched everything, still not found.  */
624 
625   return (unsigned long) -1;
626 
627  try_parent:
628   if (fp->ctf_parent)
629     return ctf_lookup_symbol_idx (fp->ctf_parent, symname);
630   else
631     {
632       ctf_set_errno (fp, err);
633       return (unsigned long) -1;
634     }
635 oom:
636   ctf_set_errno (fp, ENOMEM);
637   ctf_err_warn (fp, 0, ENOMEM, _("cannot allocate memory for symbol "
638 				 "lookup hashtab"));
639   return (unsigned long) -1;
640 
641 }
642 
643 /* Iterate over all symbols with types: if FUNC, function symbols, otherwise,
644    data symbols.  The name argument is not optional.  The return order is
645    arbitrary, though is likely to be in symbol index or name order.  You can
646    change the value of 'functions' in the middle of iteration over non-dynamic
647    dicts, but doing so on dynamic dicts will fail.  (This is probably not very
648    useful, but there is no reason to prohibit it.)  */
649 
650 ctf_id_t
ctf_symbol_next(ctf_dict_t * fp,ctf_next_t ** it,const char ** name,int functions)651 ctf_symbol_next (ctf_dict_t *fp, ctf_next_t **it, const char **name,
652 		 int functions)
653 {
654   ctf_id_t sym;
655   ctf_next_t *i = *it;
656   int err;
657 
658   if (!i)
659     {
660       if ((i = ctf_next_create ()) == NULL)
661 	return ctf_set_errno (fp, ENOMEM);
662 
663       i->cu.ctn_fp = fp;
664       i->ctn_iter_fun = (void (*) (void)) ctf_symbol_next;
665       i->ctn_n = 0;
666       *it = i;
667     }
668 
669   if ((void (*) (void)) ctf_symbol_next != i->ctn_iter_fun)
670     return (ctf_set_errno (fp, ECTF_NEXT_WRONGFUN));
671 
672   if (fp != i->cu.ctn_fp)
673     return (ctf_set_errno (fp, ECTF_NEXT_WRONGFP));
674 
675   /* We intentionally use raw access, not ctf_lookup_by_symbol, to avoid
676      incurring additional sorting cost for unsorted symtypetabs coming from the
677      compiler, to allow ctf_symbol_next to work in the absence of a symtab, and
678      finally because it's easier to work out what the name of each symbol is if
679      we do that.  */
680 
681   if (fp->ctf_flags & LCTF_RDWR)
682     {
683       ctf_dynhash_t *dynh = functions ? fp->ctf_funchash : fp->ctf_objthash;
684       void *dyn_name = NULL, *dyn_value = NULL;
685 
686       if (!dynh)
687 	{
688 	  ctf_next_destroy (i);
689 	  return (ctf_set_errno (fp, ECTF_NEXT_END));
690 	}
691 
692       err = ctf_dynhash_next (dynh, &i->ctn_next, &dyn_name, &dyn_value);
693       /* This covers errors and also end-of-iteration.  */
694       if (err != 0)
695 	{
696 	  ctf_next_destroy (i);
697 	  *it = NULL;
698 	  return ctf_set_errno (fp, err);
699 	}
700 
701       *name = dyn_name;
702       sym = (ctf_id_t) (uintptr_t) dyn_value;
703     }
704   else if ((!functions && fp->ctf_objtidx_names) ||
705 	   (functions && fp->ctf_funcidx_names))
706     {
707       ctf_header_t *hp = fp->ctf_header;
708       uint32_t *idx = functions ? fp->ctf_funcidx_names : fp->ctf_objtidx_names;
709       uint32_t *tab;
710       size_t len;
711 
712       if (functions)
713 	{
714 	  len = (hp->cth_varoff - hp->cth_funcidxoff) / sizeof (uint32_t);
715 	  tab = (uint32_t *) (fp->ctf_buf + hp->cth_funcoff);
716 	}
717       else
718 	{
719 	  len = (hp->cth_funcidxoff - hp->cth_objtidxoff) / sizeof (uint32_t);
720 	  tab = (uint32_t *) (fp->ctf_buf + hp->cth_objtoff);
721 	}
722 
723       do
724 	{
725 	  if (i->ctn_n >= len)
726 	    goto end;
727 
728 	  *name = ctf_strptr (fp, idx[i->ctn_n]);
729 	  sym = tab[i->ctn_n++];
730 	}
731       while (sym == -1u || sym == 0);
732     }
733   else
734     {
735       /* Skip over pads in ctf_xslate, padding for typeless symbols in the
736 	 symtypetab itself, and symbols in the wrong table.  */
737       for (; i->ctn_n < fp->ctf_nsyms; i->ctn_n++)
738 	{
739 	  ctf_header_t *hp = fp->ctf_header;
740 
741 	  if (fp->ctf_sxlate[i->ctn_n] == -1u)
742 	    continue;
743 
744 	  sym = *(uint32_t *) ((uintptr_t) fp->ctf_buf + fp->ctf_sxlate[i->ctn_n]);
745 
746 	  if (sym == 0)
747 	    continue;
748 
749 	  if (functions)
750 	    {
751 	      if (fp->ctf_sxlate[i->ctn_n] >= hp->cth_funcoff
752 		  && fp->ctf_sxlate[i->ctn_n] < hp->cth_objtidxoff)
753 		break;
754 	    }
755 	  else
756 	    {
757 	      if (fp->ctf_sxlate[i->ctn_n] >= hp->cth_objtoff
758 		  && fp->ctf_sxlate[i->ctn_n] < hp->cth_funcoff)
759 		break;
760 	    }
761 	}
762 
763       if (i->ctn_n >= fp->ctf_nsyms)
764 	goto end;
765 
766       *name = ctf_lookup_symbol_name (fp, i->ctn_n++);
767     }
768 
769   return sym;
770 
771  end:
772   ctf_next_destroy (i);
773   *it = NULL;
774   return (ctf_set_errno (fp, ECTF_NEXT_END));
775 }
776 
777 /* A bsearch function for function and object index names.  */
778 
779 static int
ctf_lookup_idx_name(const void * key_,const void * idx_)780 ctf_lookup_idx_name (const void *key_, const void *idx_)
781 {
782   const ctf_lookup_idx_key_t *key = key_;
783   const uint32_t *idx = idx_;
784 
785   return (strcmp (key->clik_name, ctf_strptr (key->clik_fp, key->clik_names[*idx])));
786 }
787 
788 /* Given a symbol name or (failing that) number, look up that symbol in the
789    function or object index table (which must exist).  Return 0 if not found
790    there (or pad).  */
791 
792 static ctf_id_t
ctf_try_lookup_indexed(ctf_dict_t * fp,unsigned long symidx,const char * symname,int is_function)793 ctf_try_lookup_indexed (ctf_dict_t *fp, unsigned long symidx,
794 			const char *symname, int is_function)
795 {
796   struct ctf_header *hp = fp->ctf_header;
797   uint32_t *symtypetab;
798   uint32_t *names;
799   uint32_t *sxlate;
800   size_t nidx;
801 
802   if (symname == NULL)
803     symname = ctf_lookup_symbol_name (fp, symidx);
804 
805   ctf_dprintf ("Looking up type of object with symtab idx %lx or name %s in "
806 	       "indexed symtypetab\n", symidx, symname);
807 
808   if (symname[0] == '\0')
809     return -1;					/* errno is set for us.  */
810 
811   if (is_function)
812     {
813       if (!fp->ctf_funcidx_sxlate)
814 	{
815 	  if ((fp->ctf_funcidx_sxlate
816 	       = ctf_symidx_sort (fp, (uint32_t *)
817 				  (fp->ctf_buf + hp->cth_funcidxoff),
818 				  &fp->ctf_nfuncidx,
819 				  hp->cth_varoff - hp->cth_funcidxoff))
820 	      == NULL)
821 	    {
822 	      ctf_err_warn (fp, 0, 0, _("cannot sort function symidx"));
823 	      return -1;				/* errno is set for us.  */
824 	    }
825 	}
826       symtypetab = (uint32_t *) (fp->ctf_buf + hp->cth_funcoff);
827       sxlate = fp->ctf_funcidx_sxlate;
828       names = fp->ctf_funcidx_names;
829       nidx = fp->ctf_nfuncidx;
830     }
831   else
832     {
833       if (!fp->ctf_objtidx_sxlate)
834 	{
835 	  if ((fp->ctf_objtidx_sxlate
836 	       = ctf_symidx_sort (fp, (uint32_t *)
837 				  (fp->ctf_buf + hp->cth_objtidxoff),
838 				  &fp->ctf_nobjtidx,
839 				  hp->cth_funcidxoff - hp->cth_objtidxoff))
840 	      == NULL)
841 	    {
842 	      ctf_err_warn (fp, 0, 0, _("cannot sort object symidx"));
843 	      return -1;				/* errno is set for us. */
844 	    }
845 	}
846 
847       symtypetab = (uint32_t *) (fp->ctf_buf + hp->cth_objtoff);
848       sxlate = fp->ctf_objtidx_sxlate;
849       names = fp->ctf_objtidx_names;
850       nidx = fp->ctf_nobjtidx;
851     }
852 
853   ctf_lookup_idx_key_t key = { fp, symname, names };
854   uint32_t *idx;
855 
856   idx = bsearch (&key, sxlate, nidx, sizeof (uint32_t), ctf_lookup_idx_name);
857 
858   if (!idx)
859     {
860       ctf_dprintf ("%s not found in idx\n", symname);
861       return 0;
862     }
863 
864   /* Should be impossible, but be paranoid.  */
865   if ((idx - sxlate) > (ptrdiff_t) nidx)
866     return (ctf_set_errno (fp, ECTF_CORRUPT));
867 
868   ctf_dprintf ("Symbol %lx (%s) is of type %x\n", symidx, symname,
869 	       symtypetab[*idx]);
870   return symtypetab[*idx];
871 }
872 
873 /* Given a symbol name or (if NULL) symbol index, return the type of the
874    function or data object described by the corresponding entry in the symbol
875    table.  We can only return symbols in read-only dicts and in dicts for which
876    ctf_link_shuffle_syms has been called to assign symbol indexes to symbol
877    names.  */
878 
879 static ctf_id_t
ctf_lookup_by_sym_or_name(ctf_dict_t * fp,unsigned long symidx,const char * symname)880 ctf_lookup_by_sym_or_name (ctf_dict_t *fp, unsigned long symidx,
881 			   const char *symname)
882 {
883   const ctf_sect_t *sp = &fp->ctf_symtab;
884   ctf_id_t type = 0;
885   int err = 0;
886 
887   /* Shuffled dynsymidx present?  Use that.  */
888   if (fp->ctf_dynsymidx)
889     {
890       const ctf_link_sym_t *sym;
891 
892       if (symname)
893 	ctf_dprintf ("Looking up type of object with symname %s in "
894 		     "writable dict symtypetab\n", symname);
895       else
896 	ctf_dprintf ("Looking up type of object with symtab idx %lx in "
897 		     "writable dict symtypetab\n", symidx);
898 
899       /* The dict must be dynamic.  */
900       if (!ctf_assert (fp, fp->ctf_flags & LCTF_RDWR))
901 	return CTF_ERR;
902 
903       /* No name? Need to look it up.  */
904       if (!symname)
905 	{
906 	  err = EINVAL;
907 	  if (symidx > fp->ctf_dynsymmax)
908 	    goto try_parent;
909 
910 	  sym = fp->ctf_dynsymidx[symidx];
911 	  err = ECTF_NOTYPEDAT;
912 	  if (!sym || (sym->st_shndx != STT_OBJECT && sym->st_shndx != STT_FUNC))
913 	    goto try_parent;
914 
915 	  if (!ctf_assert (fp, !sym->st_nameidx_set))
916 	    return CTF_ERR;
917 	  symname = sym->st_name;
918      }
919 
920       if (fp->ctf_objthash == NULL
921 	  || ((type = (ctf_id_t) (uintptr_t)
922 	       ctf_dynhash_lookup (fp->ctf_objthash, symname)) == 0))
923 	{
924 	  if (fp->ctf_funchash == NULL
925 	      || ((type = (ctf_id_t) (uintptr_t)
926 		   ctf_dynhash_lookup (fp->ctf_funchash, symname)) == 0))
927 	    goto try_parent;
928 	}
929 
930       return type;
931     }
932 
933   /* Lookup by name in a dynamic dict: just do it directly.  */
934   if (symname && fp->ctf_flags & LCTF_RDWR)
935     {
936       if (fp->ctf_objthash == NULL
937 	  || ((type = (ctf_id_t) (uintptr_t)
938 	       ctf_dynhash_lookup (fp->ctf_objthash, symname)) == 0))
939 	{
940 	  if (fp->ctf_funchash == NULL
941 	      || ((type = (ctf_id_t) (uintptr_t)
942 		   ctf_dynhash_lookup (fp->ctf_funchash, symname)) == 0))
943 	    goto try_parent;
944 	}
945       return type;
946     }
947 
948   err = ECTF_NOSYMTAB;
949   if (sp->cts_data == NULL)
950     goto try_parent;
951 
952   /* This covers both out-of-range lookups and a dynamic dict which hasn't been
953      shuffled yet.  */
954   err = EINVAL;
955   if (symname == NULL && symidx >= fp->ctf_nsyms)
956     goto try_parent;
957 
958   if (fp->ctf_objtidx_names)
959     {
960       if ((type = ctf_try_lookup_indexed (fp, symidx, symname, 0)) == CTF_ERR)
961 	return CTF_ERR;				/* errno is set for us.  */
962     }
963   if (type == 0 && fp->ctf_funcidx_names)
964     {
965       if ((type = ctf_try_lookup_indexed (fp, symidx, symname, 1)) == CTF_ERR)
966 	return CTF_ERR;				/* errno is set for us.  */
967     }
968   if (type != 0)
969     return type;
970 
971   err = ECTF_NOTYPEDAT;
972   if (fp->ctf_objtidx_names && fp->ctf_funcidx_names)
973     goto try_parent;
974 
975   /* Table must be nonindexed.  */
976 
977   ctf_dprintf ("Looking up object type %lx in 1:1 dict symtypetab\n", symidx);
978 
979   if (symname != NULL)
980     if ((symidx = ctf_lookup_symbol_idx (fp, symname)) == (unsigned long) -1)
981       goto try_parent;
982 
983   if (fp->ctf_sxlate[symidx] == -1u)
984     goto try_parent;
985 
986   type = *(uint32_t *) ((uintptr_t) fp->ctf_buf + fp->ctf_sxlate[symidx]);
987 
988   if (type == 0)
989     goto try_parent;
990 
991   return type;
992  try_parent:
993   if (fp->ctf_parent)
994     {
995       ctf_id_t ret = ctf_lookup_by_sym_or_name (fp->ctf_parent, symidx,
996 						symname);
997       if (ret == CTF_ERR)
998 	ctf_set_errno (fp, ctf_errno (fp->ctf_parent));
999       return ret;
1000     }
1001   else
1002     return (ctf_set_errno (fp, err));
1003 }
1004 
1005 /* Given a symbol table index, return the type of the function or data object
1006    described by the corresponding entry in the symbol table.  */
1007 ctf_id_t
ctf_lookup_by_symbol(ctf_dict_t * fp,unsigned long symidx)1008 ctf_lookup_by_symbol (ctf_dict_t *fp, unsigned long symidx)
1009 {
1010   return ctf_lookup_by_sym_or_name (fp, symidx, NULL);
1011 }
1012 
1013 /* Given a symbol name, return the type of the function or data object described
1014    by the corresponding entry in the symbol table.  */
1015 ctf_id_t
ctf_lookup_by_symbol_name(ctf_dict_t * fp,const char * symname)1016 ctf_lookup_by_symbol_name (ctf_dict_t *fp, const char *symname)
1017 {
1018   return ctf_lookup_by_sym_or_name (fp, 0, symname);
1019 }
1020 
1021 /* Given a symbol table index, return the info for the function described
1022    by the corresponding entry in the symbol table, which may be a function
1023    symbol or may be a data symbol that happens to be a function pointer.  */
1024 
1025 int
ctf_func_info(ctf_dict_t * fp,unsigned long symidx,ctf_funcinfo_t * fip)1026 ctf_func_info (ctf_dict_t *fp, unsigned long symidx, ctf_funcinfo_t *fip)
1027 {
1028   ctf_id_t type;
1029 
1030   if ((type = ctf_lookup_by_symbol (fp, symidx)) == CTF_ERR)
1031     return -1;					/* errno is set for us.  */
1032 
1033   if (ctf_type_kind (fp, type) != CTF_K_FUNCTION)
1034     return (ctf_set_errno (fp, ECTF_NOTFUNC));
1035 
1036   return ctf_func_type_info (fp, type, fip);
1037 }
1038 
1039 /* Given a symbol table index, return the arguments for the function described
1040    by the corresponding entry in the symbol table.  */
1041 
1042 int
ctf_func_args(ctf_dict_t * fp,unsigned long symidx,uint32_t argc,ctf_id_t * argv)1043 ctf_func_args (ctf_dict_t *fp, unsigned long symidx, uint32_t argc,
1044 	       ctf_id_t *argv)
1045 {
1046   ctf_id_t type;
1047 
1048   if ((type = ctf_lookup_by_symbol (fp, symidx)) == CTF_ERR)
1049     return -1;					/* errno is set for us.  */
1050 
1051   if (ctf_type_kind (fp, type) != CTF_K_FUNCTION)
1052     return (ctf_set_errno (fp, ECTF_NOTFUNC));
1053 
1054   return ctf_func_type_args (fp, type, argc, argv);
1055 }
1056