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