17d62b00eSchristos /* Symbol, variable and name lookup. 2*6881a400Schristos Copyright (C) 2019-2022 Free Software Foundation, Inc. 37d62b00eSchristos 47d62b00eSchristos This file is part of libctf. 57d62b00eSchristos 67d62b00eSchristos libctf is free software; you can redistribute it and/or modify it under 77d62b00eSchristos the terms of the GNU General Public License as published by the Free 87d62b00eSchristos Software Foundation; either version 3, or (at your option) any later 97d62b00eSchristos version. 107d62b00eSchristos 117d62b00eSchristos This program is distributed in the hope that it will be useful, but 127d62b00eSchristos WITHOUT ANY WARRANTY; without even the implied warranty of 137d62b00eSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 147d62b00eSchristos See the GNU General Public License for more details. 157d62b00eSchristos 167d62b00eSchristos You should have received a copy of the GNU General Public License 177d62b00eSchristos along with this program; see the file COPYING. If not see 187d62b00eSchristos <http://www.gnu.org/licenses/>. */ 197d62b00eSchristos 207d62b00eSchristos #include <ctf-impl.h> 217d62b00eSchristos #include <elf.h> 227d62b00eSchristos #include <string.h> 23*6881a400Schristos #include <assert.h> 24*6881a400Schristos 25*6881a400Schristos /* Grow the pptrtab so that it is at least NEW_LEN long. */ 26*6881a400Schristos static int 27*6881a400Schristos grow_pptrtab (ctf_dict_t *fp, size_t new_len) 28*6881a400Schristos { 29*6881a400Schristos uint32_t *new_pptrtab; 30*6881a400Schristos 31*6881a400Schristos if ((new_pptrtab = realloc (fp->ctf_pptrtab, sizeof (uint32_t) 32*6881a400Schristos * new_len)) == NULL) 33*6881a400Schristos return (ctf_set_errno (fp, ENOMEM)); 34*6881a400Schristos 35*6881a400Schristos fp->ctf_pptrtab = new_pptrtab; 36*6881a400Schristos 37*6881a400Schristos memset (fp->ctf_pptrtab + fp->ctf_pptrtab_len, 0, 38*6881a400Schristos sizeof (uint32_t) * (new_len - fp->ctf_pptrtab_len)); 39*6881a400Schristos 40*6881a400Schristos fp->ctf_pptrtab_len = new_len; 41*6881a400Schristos return 0; 42*6881a400Schristos } 43*6881a400Schristos 44*6881a400Schristos /* Update entries in the pptrtab that relate to types newly added in the 45*6881a400Schristos child. */ 46*6881a400Schristos static int 47*6881a400Schristos refresh_pptrtab (ctf_dict_t *fp, ctf_dict_t *pfp) 48*6881a400Schristos { 49*6881a400Schristos uint32_t i; 50*6881a400Schristos for (i = fp->ctf_pptrtab_typemax; i <= fp->ctf_typemax; i++) 51*6881a400Schristos { 52*6881a400Schristos ctf_id_t type = LCTF_INDEX_TO_TYPE (fp, i, 1); 53*6881a400Schristos ctf_id_t reffed_type; 54*6881a400Schristos 55*6881a400Schristos if (ctf_type_kind (fp, type) != CTF_K_POINTER) 56*6881a400Schristos continue; 57*6881a400Schristos 58*6881a400Schristos reffed_type = ctf_type_reference (fp, type); 59*6881a400Schristos 60*6881a400Schristos if (LCTF_TYPE_ISPARENT (fp, reffed_type)) 61*6881a400Schristos { 62*6881a400Schristos uint32_t idx = LCTF_TYPE_TO_INDEX (fp, reffed_type); 63*6881a400Schristos 64*6881a400Schristos /* Guard against references to invalid types. No need to consider 65*6881a400Schristos the CTF dict corrupt in this case: this pointer just can't be a 66*6881a400Schristos pointer to any type we know about. */ 67*6881a400Schristos if (idx <= pfp->ctf_typemax) 68*6881a400Schristos { 69*6881a400Schristos if (idx >= fp->ctf_pptrtab_len 70*6881a400Schristos && grow_pptrtab (fp, pfp->ctf_ptrtab_len) < 0) 71*6881a400Schristos return -1; /* errno is set for us. */ 72*6881a400Schristos 73*6881a400Schristos fp->ctf_pptrtab[idx] = i; 74*6881a400Schristos } 75*6881a400Schristos } 76*6881a400Schristos } 77*6881a400Schristos 78*6881a400Schristos fp->ctf_pptrtab_typemax = fp->ctf_typemax; 79*6881a400Schristos 80*6881a400Schristos return 0; 81*6881a400Schristos } 827d62b00eSchristos 837d62b00eSchristos /* Compare the given input string and length against a table of known C storage 847d62b00eSchristos qualifier keywords. We just ignore these in ctf_lookup_by_name, below. To 857d62b00eSchristos do this quickly, we use a pre-computed Perfect Hash Function similar to the 867d62b00eSchristos technique originally described in the classic paper: 877d62b00eSchristos 887d62b00eSchristos R.J. Cichelli, "Minimal Perfect Hash Functions Made Simple", 897d62b00eSchristos Communications of the ACM, Volume 23, Issue 1, January 1980, pp. 17-19. 907d62b00eSchristos 917d62b00eSchristos For an input string S of length N, we use hash H = S[N - 1] + N - 105, which 927d62b00eSchristos for the current set of qualifiers yields a unique H in the range [0 .. 20]. 937d62b00eSchristos The hash can be modified when the keyword set changes as necessary. We also 947d62b00eSchristos store the length of each keyword and check it prior to the final strcmp(). 957d62b00eSchristos 967d62b00eSchristos TODO: just use gperf. */ 977d62b00eSchristos 987d62b00eSchristos static int 997d62b00eSchristos isqualifier (const char *s, size_t len) 1007d62b00eSchristos { 1017d62b00eSchristos static const struct qual 1027d62b00eSchristos { 1037d62b00eSchristos const char *q_name; 1047d62b00eSchristos size_t q_len; 1057d62b00eSchristos } qhash[] = { 1067d62b00eSchristos {"static", 6}, {"", 0}, {"", 0}, {"", 0}, 1077d62b00eSchristos {"volatile", 8}, {"", 0}, {"", 0}, {"", 0}, {"", 0}, 1087d62b00eSchristos {"", 0}, {"auto", 4}, {"extern", 6}, {"", 0}, {"", 0}, 1097d62b00eSchristos {"", 0}, {"", 0}, {"const", 5}, {"register", 8}, 1107d62b00eSchristos {"", 0}, {"restrict", 8}, {"_Restrict", 9} 1117d62b00eSchristos }; 1127d62b00eSchristos 1137d62b00eSchristos int h = s[len - 1] + (int) len - 105; 114*6881a400Schristos const struct qual *qp; 1157d62b00eSchristos 116*6881a400Schristos if (h < 0 || (size_t) h >= sizeof (qhash) / sizeof (qhash[0])) 117*6881a400Schristos return 0; 118*6881a400Schristos 119*6881a400Schristos qp = &qhash[h]; 120*6881a400Schristos 121*6881a400Schristos return ((size_t) len == qp->q_len && 1227d62b00eSchristos strncmp (qp->q_name, s, qp->q_len) == 0); 1237d62b00eSchristos } 1247d62b00eSchristos 1257d62b00eSchristos /* Attempt to convert the given C type name into the corresponding CTF type ID. 1267d62b00eSchristos It is not possible to do complete and proper conversion of type names 1277d62b00eSchristos without implementing a more full-fledged parser, which is necessary to 1287d62b00eSchristos handle things like types that are function pointers to functions that 1297d62b00eSchristos have arguments that are function pointers, and fun stuff like that. 1307d62b00eSchristos Instead, this function implements a very simple conversion algorithm that 1317d62b00eSchristos finds the things that we actually care about: structs, unions, enums, 1327d62b00eSchristos integers, floats, typedefs, and pointers to any of these named types. */ 1337d62b00eSchristos 134*6881a400Schristos static ctf_id_t 135*6881a400Schristos ctf_lookup_by_name_internal (ctf_dict_t *fp, ctf_dict_t *child, 136*6881a400Schristos const char *name) 1377d62b00eSchristos { 1387d62b00eSchristos static const char delimiters[] = " \t\n\r\v\f*"; 1397d62b00eSchristos 1407d62b00eSchristos const ctf_lookup_t *lp; 1417d62b00eSchristos const char *p, *q, *end; 1427d62b00eSchristos ctf_id_t type = 0; 1437d62b00eSchristos ctf_id_t ntype, ptype; 1447d62b00eSchristos 1457d62b00eSchristos if (name == NULL) 1467d62b00eSchristos return (ctf_set_errno (fp, EINVAL)); 1477d62b00eSchristos 1487d62b00eSchristos for (p = name, end = name + strlen (name); *p != '\0'; p = q) 1497d62b00eSchristos { 1507d62b00eSchristos while (isspace ((int) *p)) 1517d62b00eSchristos p++; /* Skip leading whitespace. */ 1527d62b00eSchristos 1537d62b00eSchristos if (p == end) 1547d62b00eSchristos break; 1557d62b00eSchristos 1567d62b00eSchristos if ((q = strpbrk (p + 1, delimiters)) == NULL) 1577d62b00eSchristos q = end; /* Compare until end. */ 1587d62b00eSchristos 1597d62b00eSchristos if (*p == '*') 1607d62b00eSchristos { 161*6881a400Schristos /* Find a pointer to type by looking in child->ctf_pptrtab (if child 162*6881a400Schristos is set) and fp->ctf_ptrtab. If we can't find a pointer to the 163*6881a400Schristos given type, see if we can compute a pointer to the type resulting 164*6881a400Schristos from resolving the type down to its base type and use that instead. 165*6881a400Schristos This helps with cases where the CTF data includes "struct foo *" 166*6881a400Schristos but not "foo_t *" and the user tries to access "foo_t *" in the 167*6881a400Schristos debugger. 1687d62b00eSchristos 169*6881a400Schristos There is extra complexity here because uninitialized elements in 170*6881a400Schristos the pptrtab and ptrtab are set to zero, but zero (as the type ID 171*6881a400Schristos meaning the unimplemented type) is a valid return type from 172*6881a400Schristos ctf_lookup_by_name. (Pointers to types are never of type 0, so 173*6881a400Schristos this is unambiguous, just fiddly to deal with.) */ 1747d62b00eSchristos 175*6881a400Schristos uint32_t idx = LCTF_TYPE_TO_INDEX (fp, type); 176*6881a400Schristos int in_child = 0; 177*6881a400Schristos 178*6881a400Schristos ntype = CTF_ERR; 179*6881a400Schristos if (child && idx < child->ctf_pptrtab_len) 180*6881a400Schristos { 181*6881a400Schristos ntype = child->ctf_pptrtab[idx]; 182*6881a400Schristos if (ntype) 183*6881a400Schristos in_child = 1; 184*6881a400Schristos else 185*6881a400Schristos ntype = CTF_ERR; 186*6881a400Schristos } 187*6881a400Schristos 188*6881a400Schristos if (ntype == CTF_ERR) 189*6881a400Schristos { 190*6881a400Schristos ntype = fp->ctf_ptrtab[idx]; 1917d62b00eSchristos if (ntype == 0) 192*6881a400Schristos ntype = CTF_ERR; 1937d62b00eSchristos } 1947d62b00eSchristos 195*6881a400Schristos /* Try resolving to its base type and check again. */ 196*6881a400Schristos if (ntype == CTF_ERR) 197*6881a400Schristos { 198*6881a400Schristos if (child) 199*6881a400Schristos ntype = ctf_type_resolve_unsliced (child, type); 200*6881a400Schristos else 201*6881a400Schristos ntype = ctf_type_resolve_unsliced (fp, type); 202*6881a400Schristos 203*6881a400Schristos if (ntype == CTF_ERR) 204*6881a400Schristos goto notype; 205*6881a400Schristos 206*6881a400Schristos idx = LCTF_TYPE_TO_INDEX (fp, ntype); 207*6881a400Schristos 208*6881a400Schristos ntype = CTF_ERR; 209*6881a400Schristos if (child && idx < child->ctf_pptrtab_len) 210*6881a400Schristos { 211*6881a400Schristos ntype = child->ctf_pptrtab[idx]; 212*6881a400Schristos if (ntype) 213*6881a400Schristos in_child = 1; 214*6881a400Schristos else 215*6881a400Schristos ntype = CTF_ERR; 216*6881a400Schristos } 217*6881a400Schristos 218*6881a400Schristos if (ntype == CTF_ERR) 219*6881a400Schristos { 220*6881a400Schristos ntype = fp->ctf_ptrtab[idx]; 221*6881a400Schristos if (ntype == 0) 222*6881a400Schristos ntype = CTF_ERR; 223*6881a400Schristos } 224*6881a400Schristos if (ntype == CTF_ERR) 225*6881a400Schristos goto notype; 226*6881a400Schristos } 227*6881a400Schristos 228*6881a400Schristos type = LCTF_INDEX_TO_TYPE (fp, ntype, (fp->ctf_flags & LCTF_CHILD) 229*6881a400Schristos || in_child); 230*6881a400Schristos 231*6881a400Schristos /* We are looking up a type in the parent, but the pointed-to type is 232*6881a400Schristos in the child. Switch to looking in the child: if we need to go 233*6881a400Schristos back into the parent, we can recurse again. */ 234*6881a400Schristos if (in_child) 235*6881a400Schristos { 236*6881a400Schristos fp = child; 237*6881a400Schristos child = NULL; 238*6881a400Schristos } 2397d62b00eSchristos 2407d62b00eSchristos q = p + 1; 2417d62b00eSchristos continue; 2427d62b00eSchristos } 2437d62b00eSchristos 2447d62b00eSchristos if (isqualifier (p, (size_t) (q - p))) 2457d62b00eSchristos continue; /* Skip qualifier keyword. */ 2467d62b00eSchristos 2477d62b00eSchristos for (lp = fp->ctf_lookups; lp->ctl_prefix != NULL; lp++) 2487d62b00eSchristos { 2497d62b00eSchristos /* TODO: This is not MT-safe. */ 2507d62b00eSchristos if ((lp->ctl_prefix[0] == '\0' || 2517d62b00eSchristos strncmp (p, lp->ctl_prefix, (size_t) (q - p)) == 0) && 2527d62b00eSchristos (size_t) (q - p) >= lp->ctl_len) 2537d62b00eSchristos { 2547d62b00eSchristos for (p += lp->ctl_len; isspace ((int) *p); p++) 2557d62b00eSchristos continue; /* Skip prefix and next whitespace. */ 2567d62b00eSchristos 2577d62b00eSchristos if ((q = strchr (p, '*')) == NULL) 2587d62b00eSchristos q = end; /* Compare until end. */ 2597d62b00eSchristos 2607d62b00eSchristos while (isspace ((int) q[-1])) 2617d62b00eSchristos q--; /* Exclude trailing whitespace. */ 2627d62b00eSchristos 2637d62b00eSchristos /* Expand and/or allocate storage for a slice of the name, then 2647d62b00eSchristos copy it in. */ 2657d62b00eSchristos 2667d62b00eSchristos if (fp->ctf_tmp_typeslicelen >= (size_t) (q - p) + 1) 2677d62b00eSchristos { 2687d62b00eSchristos memcpy (fp->ctf_tmp_typeslice, p, (size_t) (q - p)); 2697d62b00eSchristos fp->ctf_tmp_typeslice[(size_t) (q - p)] = '\0'; 2707d62b00eSchristos } 2717d62b00eSchristos else 2727d62b00eSchristos { 2737d62b00eSchristos free (fp->ctf_tmp_typeslice); 2747d62b00eSchristos fp->ctf_tmp_typeslice = xstrndup (p, (size_t) (q - p)); 2757d62b00eSchristos if (fp->ctf_tmp_typeslice == NULL) 2767d62b00eSchristos { 277*6881a400Schristos ctf_set_errno (fp, ENOMEM); 2787d62b00eSchristos return CTF_ERR; 2797d62b00eSchristos } 2807d62b00eSchristos } 2817d62b00eSchristos 2827d62b00eSchristos if ((type = ctf_lookup_by_rawhash (fp, lp->ctl_hash, 2837d62b00eSchristos fp->ctf_tmp_typeslice)) == 0) 284*6881a400Schristos goto notype; 2857d62b00eSchristos 2867d62b00eSchristos break; 2877d62b00eSchristos } 2887d62b00eSchristos } 2897d62b00eSchristos 2907d62b00eSchristos if (lp->ctl_prefix == NULL) 291*6881a400Schristos goto notype; 2927d62b00eSchristos } 2937d62b00eSchristos 2947d62b00eSchristos if (*p != '\0' || type == 0) 2957d62b00eSchristos return (ctf_set_errno (fp, ECTF_SYNTAX)); 2967d62b00eSchristos 2977d62b00eSchristos return type; 2987d62b00eSchristos 299*6881a400Schristos notype: 300*6881a400Schristos ctf_set_errno (fp, ECTF_NOTYPE); 301*6881a400Schristos if (fp->ctf_parent != NULL) 302*6881a400Schristos { 303*6881a400Schristos /* Need to look up in the parent, from the child's perspective. 304*6881a400Schristos Make sure the pptrtab is up to date. */ 305*6881a400Schristos 306*6881a400Schristos if (fp->ctf_pptrtab_typemax < fp->ctf_typemax) 307*6881a400Schristos { 308*6881a400Schristos if (refresh_pptrtab (fp, fp->ctf_parent) < 0) 309*6881a400Schristos return -1; /* errno is set for us. */ 310*6881a400Schristos } 311*6881a400Schristos 312*6881a400Schristos if ((ptype = ctf_lookup_by_name_internal (fp->ctf_parent, fp, 313*6881a400Schristos name)) != CTF_ERR) 3147d62b00eSchristos return ptype; 315*6881a400Schristos return (ctf_set_errno (fp, ctf_errno (fp->ctf_parent))); 316*6881a400Schristos } 3177d62b00eSchristos 3187d62b00eSchristos return CTF_ERR; 3197d62b00eSchristos } 3207d62b00eSchristos 3217d62b00eSchristos ctf_id_t 322*6881a400Schristos ctf_lookup_by_name (ctf_dict_t *fp, const char *name) 3237d62b00eSchristos { 324*6881a400Schristos return ctf_lookup_by_name_internal (fp, NULL, name); 3257d62b00eSchristos } 3267d62b00eSchristos 3277d62b00eSchristos /* Return the pointer to the internal CTF type data corresponding to the 3287d62b00eSchristos given type ID. If the ID is invalid, the function returns NULL. 3297d62b00eSchristos This function is not exported outside of the library. */ 3307d62b00eSchristos 3317d62b00eSchristos const ctf_type_t * 332*6881a400Schristos ctf_lookup_by_id (ctf_dict_t **fpp, ctf_id_t type) 3337d62b00eSchristos { 334*6881a400Schristos ctf_dict_t *fp = *fpp; /* Caller passes in starting CTF dict. */ 3357d62b00eSchristos ctf_id_t idx; 3367d62b00eSchristos 3377d62b00eSchristos if ((fp = ctf_get_dict (fp, type)) == NULL) 3387d62b00eSchristos { 3397d62b00eSchristos (void) ctf_set_errno (*fpp, ECTF_NOPARENT); 3407d62b00eSchristos return NULL; 3417d62b00eSchristos } 3427d62b00eSchristos 3437d62b00eSchristos /* If this dict is writable, check for a dynamic type. */ 3447d62b00eSchristos 3457d62b00eSchristos if (fp->ctf_flags & LCTF_RDWR) 3467d62b00eSchristos { 3477d62b00eSchristos ctf_dtdef_t *dtd; 3487d62b00eSchristos 3497d62b00eSchristos if ((dtd = ctf_dynamic_type (fp, type)) != NULL) 3507d62b00eSchristos { 3517d62b00eSchristos *fpp = fp; 3527d62b00eSchristos return &dtd->dtd_data; 3537d62b00eSchristos } 3547d62b00eSchristos (void) ctf_set_errno (*fpp, ECTF_BADID); 3557d62b00eSchristos return NULL; 3567d62b00eSchristos } 3577d62b00eSchristos 3587d62b00eSchristos /* Check for a type in the static portion. */ 3597d62b00eSchristos 3607d62b00eSchristos idx = LCTF_TYPE_TO_INDEX (fp, type); 3617d62b00eSchristos if (idx > 0 && (unsigned long) idx <= fp->ctf_typemax) 3627d62b00eSchristos { 363*6881a400Schristos *fpp = fp; /* Function returns ending CTF dict. */ 3647d62b00eSchristos return (LCTF_INDEX_TO_TYPEPTR (fp, idx)); 3657d62b00eSchristos } 3667d62b00eSchristos 3677d62b00eSchristos (void) ctf_set_errno (*fpp, ECTF_BADID); 3687d62b00eSchristos return NULL; 3697d62b00eSchristos } 3707d62b00eSchristos 371*6881a400Schristos typedef struct ctf_lookup_idx_key 372*6881a400Schristos { 373*6881a400Schristos ctf_dict_t *clik_fp; 374*6881a400Schristos const char *clik_name; 375*6881a400Schristos uint32_t *clik_names; 376*6881a400Schristos } ctf_lookup_idx_key_t; 3777d62b00eSchristos 378*6881a400Schristos /* A bsearch function for variable names. */ 379*6881a400Schristos 380*6881a400Schristos static int 381*6881a400Schristos ctf_lookup_var (const void *key_, const void *lookup_) 382*6881a400Schristos { 383*6881a400Schristos const ctf_lookup_idx_key_t *key = key_; 384*6881a400Schristos const ctf_varent_t *lookup = lookup_; 385*6881a400Schristos 386*6881a400Schristos return (strcmp (key->clik_name, ctf_strptr (key->clik_fp, lookup->ctv_name))); 387*6881a400Schristos } 388*6881a400Schristos 389*6881a400Schristos /* Given a variable name, return the type of the variable with that name. */ 390*6881a400Schristos 391*6881a400Schristos ctf_id_t 392*6881a400Schristos ctf_lookup_variable (ctf_dict_t *fp, const char *name) 393*6881a400Schristos { 394*6881a400Schristos ctf_varent_t *ent; 395*6881a400Schristos ctf_lookup_idx_key_t key = { fp, name, NULL }; 396*6881a400Schristos 397*6881a400Schristos /* This array is sorted, so we can bsearch for it. */ 398*6881a400Schristos 399*6881a400Schristos ent = bsearch (&key, fp->ctf_vars, fp->ctf_nvars, sizeof (ctf_varent_t), 400*6881a400Schristos ctf_lookup_var); 401*6881a400Schristos 402*6881a400Schristos if (ent == NULL) 403*6881a400Schristos { 404*6881a400Schristos if (fp->ctf_parent != NULL) 405*6881a400Schristos return ctf_lookup_variable (fp->ctf_parent, name); 406*6881a400Schristos 407*6881a400Schristos return (ctf_set_errno (fp, ECTF_NOTYPEDAT)); 408*6881a400Schristos } 409*6881a400Schristos 410*6881a400Schristos return ent->ctv_type; 411*6881a400Schristos } 412*6881a400Schristos 413*6881a400Schristos typedef struct ctf_symidx_sort_arg_cb 414*6881a400Schristos { 415*6881a400Schristos ctf_dict_t *fp; 416*6881a400Schristos uint32_t *names; 417*6881a400Schristos } ctf_symidx_sort_arg_cb_t; 418*6881a400Schristos 419*6881a400Schristos static int 420*6881a400Schristos sort_symidx_by_name (const void *one_, const void *two_, void *arg_) 421*6881a400Schristos { 422*6881a400Schristos const uint32_t *one = one_; 423*6881a400Schristos const uint32_t *two = two_; 424*6881a400Schristos ctf_symidx_sort_arg_cb_t *arg = arg_; 425*6881a400Schristos 426*6881a400Schristos return (strcmp (ctf_strptr (arg->fp, arg->names[*one]), 427*6881a400Schristos ctf_strptr (arg->fp, arg->names[*two]))); 428*6881a400Schristos } 429*6881a400Schristos 430*6881a400Schristos /* Sort a symbol index section by name. Takes a 1:1 mapping of names to the 431*6881a400Schristos corresponding symbol table. Returns a lexicographically sorted array of idx 432*6881a400Schristos indexes (and thus, of indexes into the corresponding func info / data object 433*6881a400Schristos section). */ 434*6881a400Schristos 435*6881a400Schristos static uint32_t * 436*6881a400Schristos ctf_symidx_sort (ctf_dict_t *fp, uint32_t *idx, size_t *nidx, 437*6881a400Schristos size_t len) 438*6881a400Schristos { 439*6881a400Schristos uint32_t *sorted; 440*6881a400Schristos size_t i; 441*6881a400Schristos 442*6881a400Schristos if ((sorted = malloc (len)) == NULL) 443*6881a400Schristos { 444*6881a400Schristos ctf_set_errno (fp, ENOMEM); 445*6881a400Schristos return NULL; 446*6881a400Schristos } 447*6881a400Schristos 448*6881a400Schristos *nidx = len / sizeof (uint32_t); 449*6881a400Schristos for (i = 0; i < *nidx; i++) 450*6881a400Schristos sorted[i] = i; 451*6881a400Schristos 452*6881a400Schristos if (!(fp->ctf_header->cth_flags & CTF_F_IDXSORTED)) 453*6881a400Schristos { 454*6881a400Schristos ctf_symidx_sort_arg_cb_t arg = { fp, idx }; 455*6881a400Schristos ctf_dprintf ("Index section unsorted: sorting."); 456*6881a400Schristos ctf_qsort_r (sorted, *nidx, sizeof (uint32_t), sort_symidx_by_name, &arg); 457*6881a400Schristos fp->ctf_header->cth_flags |= CTF_F_IDXSORTED; 458*6881a400Schristos } 459*6881a400Schristos 460*6881a400Schristos return sorted; 461*6881a400Schristos } 462*6881a400Schristos 463*6881a400Schristos /* Given a symbol index, return the name of that symbol from the table provided 464*6881a400Schristos by ctf_link_shuffle_syms, or failing that from the secondary string table, or 465*6881a400Schristos the null string. */ 466*6881a400Schristos static const char * 467*6881a400Schristos ctf_lookup_symbol_name (ctf_dict_t *fp, unsigned long symidx) 4687d62b00eSchristos { 4697d62b00eSchristos const ctf_sect_t *sp = &fp->ctf_symtab; 470*6881a400Schristos ctf_link_sym_t sym; 471*6881a400Schristos int err; 4727d62b00eSchristos 473*6881a400Schristos if (fp->ctf_dynsymidx) 474*6881a400Schristos { 475*6881a400Schristos err = EINVAL; 476*6881a400Schristos if (symidx > fp->ctf_dynsymmax) 477*6881a400Schristos goto try_parent; 478*6881a400Schristos 479*6881a400Schristos ctf_link_sym_t *symp = fp->ctf_dynsymidx[symidx]; 480*6881a400Schristos 481*6881a400Schristos if (!symp) 482*6881a400Schristos goto try_parent; 483*6881a400Schristos 484*6881a400Schristos return symp->st_name; 485*6881a400Schristos } 486*6881a400Schristos 487*6881a400Schristos err = ECTF_NOSYMTAB; 4887d62b00eSchristos if (sp->cts_data == NULL) 489*6881a400Schristos goto try_parent; 4907d62b00eSchristos 4917d62b00eSchristos if (symidx >= fp->ctf_nsyms) 492*6881a400Schristos goto try_parent; 4937d62b00eSchristos 494*6881a400Schristos switch (sp->cts_entsize) 495*6881a400Schristos { 496*6881a400Schristos case sizeof (Elf64_Sym): 497*6881a400Schristos { 498*6881a400Schristos const Elf64_Sym *symp = (Elf64_Sym *) sp->cts_data + symidx; 499*6881a400Schristos ctf_elf64_to_link_sym (fp, &sym, symp, symidx); 500*6881a400Schristos } 501*6881a400Schristos break; 502*6881a400Schristos case sizeof (Elf32_Sym): 5037d62b00eSchristos { 5047d62b00eSchristos const Elf32_Sym *symp = (Elf32_Sym *) sp->cts_data + symidx; 505*6881a400Schristos ctf_elf32_to_link_sym (fp, &sym, symp, symidx); 506*6881a400Schristos } 507*6881a400Schristos break; 508*6881a400Schristos default: 509*6881a400Schristos ctf_set_errno (fp, ECTF_SYMTAB); 510*6881a400Schristos return _CTF_NULLSTR; 511*6881a400Schristos } 512*6881a400Schristos 513*6881a400Schristos assert (!sym.st_nameidx_set); 514*6881a400Schristos 515*6881a400Schristos return sym.st_name; 516*6881a400Schristos 517*6881a400Schristos try_parent: 518*6881a400Schristos if (fp->ctf_parent) 519*6881a400Schristos { 520*6881a400Schristos const char *ret; 521*6881a400Schristos ret = ctf_lookup_symbol_name (fp->ctf_parent, symidx); 522*6881a400Schristos if (ret == NULL) 523*6881a400Schristos ctf_set_errno (fp, ctf_errno (fp->ctf_parent)); 524*6881a400Schristos return ret; 5257d62b00eSchristos } 5267d62b00eSchristos else 5277d62b00eSchristos { 528*6881a400Schristos ctf_set_errno (fp, err); 529*6881a400Schristos return _CTF_NULLSTR; 530*6881a400Schristos } 5317d62b00eSchristos } 5327d62b00eSchristos 533*6881a400Schristos /* Given a symbol name, return the index of that symbol, or -1 on error or if 534*6881a400Schristos not found. */ 535*6881a400Schristos static unsigned long 536*6881a400Schristos ctf_lookup_symbol_idx (ctf_dict_t *fp, const char *symname) 537*6881a400Schristos { 538*6881a400Schristos const ctf_sect_t *sp = &fp->ctf_symtab; 539*6881a400Schristos ctf_link_sym_t sym; 540*6881a400Schristos void *known_idx; 541*6881a400Schristos int err; 542*6881a400Schristos ctf_dict_t *cache = fp; 5437d62b00eSchristos 544*6881a400Schristos if (fp->ctf_dynsyms) 545*6881a400Schristos { 546*6881a400Schristos err = EINVAL; 5477d62b00eSchristos 548*6881a400Schristos ctf_link_sym_t *symp; 5497d62b00eSchristos 550*6881a400Schristos if ((symp = ctf_dynhash_lookup (fp->ctf_dynsyms, symname)) == NULL) 551*6881a400Schristos goto try_parent; 5527d62b00eSchristos 553*6881a400Schristos return symp->st_symidx; 554*6881a400Schristos } 555*6881a400Schristos 556*6881a400Schristos err = ECTF_NOSYMTAB; 557*6881a400Schristos if (sp->cts_data == NULL) 558*6881a400Schristos goto try_parent; 559*6881a400Schristos 560*6881a400Schristos /* First, try a hash lookup to see if we have already spotted this symbol 561*6881a400Schristos during a past iteration: create the hash first if need be. The lifespan 562*6881a400Schristos of the strings is equal to the lifespan of the cts_data, so we don't 563*6881a400Schristos need to strdup them. If this dict was opened as part of an archive, 564*6881a400Schristos and this archive has designed a crossdict_cache to cache results that 565*6881a400Schristos are the same across all dicts in an archive, use it. */ 566*6881a400Schristos 567*6881a400Schristos if (fp->ctf_archive && fp->ctf_archive->ctfi_crossdict_cache) 568*6881a400Schristos cache = fp->ctf_archive->ctfi_crossdict_cache; 569*6881a400Schristos 570*6881a400Schristos if (!cache->ctf_symhash) 571*6881a400Schristos if ((cache->ctf_symhash = ctf_dynhash_create (ctf_hash_string, 572*6881a400Schristos ctf_hash_eq_string, 573*6881a400Schristos NULL, NULL)) == NULL) 574*6881a400Schristos goto oom; 575*6881a400Schristos 576*6881a400Schristos if (ctf_dynhash_lookup_kv (cache->ctf_symhash, symname, NULL, &known_idx)) 577*6881a400Schristos return (unsigned long) (uintptr_t) known_idx; 578*6881a400Schristos 579*6881a400Schristos /* Hash lookup unsuccessful: linear search, populating the hashtab for later 580*6881a400Schristos lookups as we go. */ 581*6881a400Schristos 582*6881a400Schristos for (; cache->ctf_symhash_latest < sp->cts_size / sp->cts_entsize; 583*6881a400Schristos cache->ctf_symhash_latest++) 584*6881a400Schristos { 585*6881a400Schristos switch (sp->cts_entsize) 586*6881a400Schristos { 587*6881a400Schristos case sizeof (Elf64_Sym): 588*6881a400Schristos { 589*6881a400Schristos Elf64_Sym *symp = (Elf64_Sym *) sp->cts_data; 590*6881a400Schristos ctf_elf64_to_link_sym (fp, &sym, &symp[cache->ctf_symhash_latest], 591*6881a400Schristos cache->ctf_symhash_latest); 592*6881a400Schristos if (!ctf_dynhash_lookup_kv (cache->ctf_symhash, sym.st_name, 593*6881a400Schristos NULL, NULL)) 594*6881a400Schristos if (ctf_dynhash_cinsert (cache->ctf_symhash, sym.st_name, 595*6881a400Schristos (const void *) (uintptr_t) 596*6881a400Schristos cache->ctf_symhash_latest) < 0) 597*6881a400Schristos goto oom; 598*6881a400Schristos if (strcmp (sym.st_name, symname) == 0) 599*6881a400Schristos return cache->ctf_symhash_latest++; 600*6881a400Schristos } 601*6881a400Schristos break; 602*6881a400Schristos case sizeof (Elf32_Sym): 603*6881a400Schristos { 604*6881a400Schristos Elf32_Sym *symp = (Elf32_Sym *) sp->cts_data; 605*6881a400Schristos ctf_elf32_to_link_sym (fp, &sym, &symp[cache->ctf_symhash_latest], 606*6881a400Schristos cache->ctf_symhash_latest); 607*6881a400Schristos if (!ctf_dynhash_lookup_kv (cache->ctf_symhash, sym.st_name, 608*6881a400Schristos NULL, NULL)) 609*6881a400Schristos if (ctf_dynhash_cinsert (cache->ctf_symhash, sym.st_name, 610*6881a400Schristos (const void *) (uintptr_t) 611*6881a400Schristos cache->ctf_symhash_latest) < 0) 612*6881a400Schristos goto oom; 613*6881a400Schristos if (strcmp (sym.st_name, symname) == 0) 614*6881a400Schristos return cache->ctf_symhash_latest++; 615*6881a400Schristos } 616*6881a400Schristos break; 617*6881a400Schristos default: 618*6881a400Schristos ctf_set_errno (fp, ECTF_SYMTAB); 619*6881a400Schristos return (unsigned long) -1; 620*6881a400Schristos } 621*6881a400Schristos } 622*6881a400Schristos 623*6881a400Schristos /* Searched everything, still not found. */ 624*6881a400Schristos 625*6881a400Schristos return (unsigned long) -1; 626*6881a400Schristos 627*6881a400Schristos try_parent: 628*6881a400Schristos if (fp->ctf_parent) 629*6881a400Schristos return ctf_lookup_symbol_idx (fp->ctf_parent, symname); 630*6881a400Schristos else 631*6881a400Schristos { 632*6881a400Schristos ctf_set_errno (fp, err); 633*6881a400Schristos return (unsigned long) -1; 634*6881a400Schristos } 635*6881a400Schristos oom: 636*6881a400Schristos ctf_set_errno (fp, ENOMEM); 637*6881a400Schristos ctf_err_warn (fp, 0, ENOMEM, _("cannot allocate memory for symbol " 638*6881a400Schristos "lookup hashtab")); 639*6881a400Schristos return (unsigned long) -1; 640*6881a400Schristos 641*6881a400Schristos } 642*6881a400Schristos 643*6881a400Schristos /* Iterate over all symbols with types: if FUNC, function symbols, otherwise, 644*6881a400Schristos data symbols. The name argument is not optional. The return order is 645*6881a400Schristos arbitrary, though is likely to be in symbol index or name order. You can 646*6881a400Schristos change the value of 'functions' in the middle of iteration over non-dynamic 647*6881a400Schristos dicts, but doing so on dynamic dicts will fail. (This is probably not very 648*6881a400Schristos useful, but there is no reason to prohibit it.) */ 649*6881a400Schristos 650*6881a400Schristos ctf_id_t 651*6881a400Schristos ctf_symbol_next (ctf_dict_t *fp, ctf_next_t **it, const char **name, 652*6881a400Schristos int functions) 653*6881a400Schristos { 654*6881a400Schristos ctf_id_t sym; 655*6881a400Schristos ctf_next_t *i = *it; 656*6881a400Schristos int err; 657*6881a400Schristos 658*6881a400Schristos if (!i) 659*6881a400Schristos { 660*6881a400Schristos if ((i = ctf_next_create ()) == NULL) 661*6881a400Schristos return ctf_set_errno (fp, ENOMEM); 662*6881a400Schristos 663*6881a400Schristos i->cu.ctn_fp = fp; 664*6881a400Schristos i->ctn_iter_fun = (void (*) (void)) ctf_symbol_next; 665*6881a400Schristos i->ctn_n = 0; 666*6881a400Schristos *it = i; 667*6881a400Schristos } 668*6881a400Schristos 669*6881a400Schristos if ((void (*) (void)) ctf_symbol_next != i->ctn_iter_fun) 670*6881a400Schristos return (ctf_set_errno (fp, ECTF_NEXT_WRONGFUN)); 671*6881a400Schristos 672*6881a400Schristos if (fp != i->cu.ctn_fp) 673*6881a400Schristos return (ctf_set_errno (fp, ECTF_NEXT_WRONGFP)); 674*6881a400Schristos 675*6881a400Schristos /* We intentionally use raw access, not ctf_lookup_by_symbol, to avoid 676*6881a400Schristos incurring additional sorting cost for unsorted symtypetabs coming from the 677*6881a400Schristos compiler, to allow ctf_symbol_next to work in the absence of a symtab, and 678*6881a400Schristos finally because it's easier to work out what the name of each symbol is if 679*6881a400Schristos we do that. */ 680*6881a400Schristos 681*6881a400Schristos if (fp->ctf_flags & LCTF_RDWR) 682*6881a400Schristos { 683*6881a400Schristos ctf_dynhash_t *dynh = functions ? fp->ctf_funchash : fp->ctf_objthash; 684*6881a400Schristos void *dyn_name = NULL, *dyn_value = NULL; 685*6881a400Schristos 686*6881a400Schristos if (!dynh) 687*6881a400Schristos { 688*6881a400Schristos ctf_next_destroy (i); 689*6881a400Schristos return (ctf_set_errno (fp, ECTF_NEXT_END)); 690*6881a400Schristos } 691*6881a400Schristos 692*6881a400Schristos err = ctf_dynhash_next (dynh, &i->ctn_next, &dyn_name, &dyn_value); 693*6881a400Schristos /* This covers errors and also end-of-iteration. */ 694*6881a400Schristos if (err != 0) 695*6881a400Schristos { 696*6881a400Schristos ctf_next_destroy (i); 697*6881a400Schristos *it = NULL; 698*6881a400Schristos return ctf_set_errno (fp, err); 699*6881a400Schristos } 700*6881a400Schristos 701*6881a400Schristos *name = dyn_name; 702*6881a400Schristos sym = (ctf_id_t) (uintptr_t) dyn_value; 703*6881a400Schristos } 704*6881a400Schristos else if ((!functions && fp->ctf_objtidx_names) || 705*6881a400Schristos (functions && fp->ctf_funcidx_names)) 706*6881a400Schristos { 707*6881a400Schristos ctf_header_t *hp = fp->ctf_header; 708*6881a400Schristos uint32_t *idx = functions ? fp->ctf_funcidx_names : fp->ctf_objtidx_names; 709*6881a400Schristos uint32_t *tab; 710*6881a400Schristos size_t len; 711*6881a400Schristos 712*6881a400Schristos if (functions) 713*6881a400Schristos { 714*6881a400Schristos len = (hp->cth_varoff - hp->cth_funcidxoff) / sizeof (uint32_t); 715*6881a400Schristos tab = (uint32_t *) (fp->ctf_buf + hp->cth_funcoff); 716*6881a400Schristos } 717*6881a400Schristos else 718*6881a400Schristos { 719*6881a400Schristos len = (hp->cth_funcidxoff - hp->cth_objtidxoff) / sizeof (uint32_t); 720*6881a400Schristos tab = (uint32_t *) (fp->ctf_buf + hp->cth_objtoff); 721*6881a400Schristos } 722*6881a400Schristos 723*6881a400Schristos do 724*6881a400Schristos { 725*6881a400Schristos if (i->ctn_n >= len) 726*6881a400Schristos goto end; 727*6881a400Schristos 728*6881a400Schristos *name = ctf_strptr (fp, idx[i->ctn_n]); 729*6881a400Schristos sym = tab[i->ctn_n++]; 730*6881a400Schristos } 731*6881a400Schristos while (sym == -1u || sym == 0); 732*6881a400Schristos } 733*6881a400Schristos else 734*6881a400Schristos { 735*6881a400Schristos /* Skip over pads in ctf_xslate, padding for typeless symbols in the 736*6881a400Schristos symtypetab itself, and symbols in the wrong table. */ 737*6881a400Schristos for (; i->ctn_n < fp->ctf_nsyms; i->ctn_n++) 738*6881a400Schristos { 739*6881a400Schristos ctf_header_t *hp = fp->ctf_header; 740*6881a400Schristos 741*6881a400Schristos if (fp->ctf_sxlate[i->ctn_n] == -1u) 742*6881a400Schristos continue; 743*6881a400Schristos 744*6881a400Schristos sym = *(uint32_t *) ((uintptr_t) fp->ctf_buf + fp->ctf_sxlate[i->ctn_n]); 745*6881a400Schristos 746*6881a400Schristos if (sym == 0) 747*6881a400Schristos continue; 748*6881a400Schristos 749*6881a400Schristos if (functions) 750*6881a400Schristos { 751*6881a400Schristos if (fp->ctf_sxlate[i->ctn_n] >= hp->cth_funcoff 752*6881a400Schristos && fp->ctf_sxlate[i->ctn_n] < hp->cth_objtidxoff) 753*6881a400Schristos break; 754*6881a400Schristos } 755*6881a400Schristos else 756*6881a400Schristos { 757*6881a400Schristos if (fp->ctf_sxlate[i->ctn_n] >= hp->cth_objtoff 758*6881a400Schristos && fp->ctf_sxlate[i->ctn_n] < hp->cth_funcoff) 759*6881a400Schristos break; 760*6881a400Schristos } 761*6881a400Schristos } 762*6881a400Schristos 763*6881a400Schristos if (i->ctn_n >= fp->ctf_nsyms) 764*6881a400Schristos goto end; 765*6881a400Schristos 766*6881a400Schristos *name = ctf_lookup_symbol_name (fp, i->ctn_n++); 767*6881a400Schristos } 768*6881a400Schristos 769*6881a400Schristos return sym; 770*6881a400Schristos 771*6881a400Schristos end: 772*6881a400Schristos ctf_next_destroy (i); 773*6881a400Schristos *it = NULL; 774*6881a400Schristos return (ctf_set_errno (fp, ECTF_NEXT_END)); 775*6881a400Schristos } 776*6881a400Schristos 777*6881a400Schristos /* A bsearch function for function and object index names. */ 778*6881a400Schristos 779*6881a400Schristos static int 780*6881a400Schristos ctf_lookup_idx_name (const void *key_, const void *idx_) 781*6881a400Schristos { 782*6881a400Schristos const ctf_lookup_idx_key_t *key = key_; 783*6881a400Schristos const uint32_t *idx = idx_; 784*6881a400Schristos 785*6881a400Schristos return (strcmp (key->clik_name, ctf_strptr (key->clik_fp, key->clik_names[*idx]))); 786*6881a400Schristos } 787*6881a400Schristos 788*6881a400Schristos /* Given a symbol name or (failing that) number, look up that symbol in the 789*6881a400Schristos function or object index table (which must exist). Return 0 if not found 790*6881a400Schristos there (or pad). */ 791*6881a400Schristos 792*6881a400Schristos static ctf_id_t 793*6881a400Schristos ctf_try_lookup_indexed (ctf_dict_t *fp, unsigned long symidx, 794*6881a400Schristos const char *symname, int is_function) 795*6881a400Schristos { 796*6881a400Schristos struct ctf_header *hp = fp->ctf_header; 797*6881a400Schristos uint32_t *symtypetab; 798*6881a400Schristos uint32_t *names; 799*6881a400Schristos uint32_t *sxlate; 800*6881a400Schristos size_t nidx; 801*6881a400Schristos 802*6881a400Schristos if (symname == NULL) 803*6881a400Schristos symname = ctf_lookup_symbol_name (fp, symidx); 804*6881a400Schristos 805*6881a400Schristos ctf_dprintf ("Looking up type of object with symtab idx %lx or name %s in " 806*6881a400Schristos "indexed symtypetab\n", symidx, symname); 807*6881a400Schristos 808*6881a400Schristos if (symname[0] == '\0') 809*6881a400Schristos return -1; /* errno is set for us. */ 810*6881a400Schristos 811*6881a400Schristos if (is_function) 812*6881a400Schristos { 813*6881a400Schristos if (!fp->ctf_funcidx_sxlate) 814*6881a400Schristos { 815*6881a400Schristos if ((fp->ctf_funcidx_sxlate 816*6881a400Schristos = ctf_symidx_sort (fp, (uint32_t *) 817*6881a400Schristos (fp->ctf_buf + hp->cth_funcidxoff), 818*6881a400Schristos &fp->ctf_nfuncidx, 819*6881a400Schristos hp->cth_varoff - hp->cth_funcidxoff)) 820*6881a400Schristos == NULL) 821*6881a400Schristos { 822*6881a400Schristos ctf_err_warn (fp, 0, 0, _("cannot sort function symidx")); 823*6881a400Schristos return -1; /* errno is set for us. */ 824*6881a400Schristos } 825*6881a400Schristos } 826*6881a400Schristos symtypetab = (uint32_t *) (fp->ctf_buf + hp->cth_funcoff); 827*6881a400Schristos sxlate = fp->ctf_funcidx_sxlate; 828*6881a400Schristos names = fp->ctf_funcidx_names; 829*6881a400Schristos nidx = fp->ctf_nfuncidx; 830*6881a400Schristos } 831*6881a400Schristos else 832*6881a400Schristos { 833*6881a400Schristos if (!fp->ctf_objtidx_sxlate) 834*6881a400Schristos { 835*6881a400Schristos if ((fp->ctf_objtidx_sxlate 836*6881a400Schristos = ctf_symidx_sort (fp, (uint32_t *) 837*6881a400Schristos (fp->ctf_buf + hp->cth_objtidxoff), 838*6881a400Schristos &fp->ctf_nobjtidx, 839*6881a400Schristos hp->cth_funcidxoff - hp->cth_objtidxoff)) 840*6881a400Schristos == NULL) 841*6881a400Schristos { 842*6881a400Schristos ctf_err_warn (fp, 0, 0, _("cannot sort object symidx")); 843*6881a400Schristos return -1; /* errno is set for us. */ 844*6881a400Schristos } 845*6881a400Schristos } 846*6881a400Schristos 847*6881a400Schristos symtypetab = (uint32_t *) (fp->ctf_buf + hp->cth_objtoff); 848*6881a400Schristos sxlate = fp->ctf_objtidx_sxlate; 849*6881a400Schristos names = fp->ctf_objtidx_names; 850*6881a400Schristos nidx = fp->ctf_nobjtidx; 851*6881a400Schristos } 852*6881a400Schristos 853*6881a400Schristos ctf_lookup_idx_key_t key = { fp, symname, names }; 854*6881a400Schristos uint32_t *idx; 855*6881a400Schristos 856*6881a400Schristos idx = bsearch (&key, sxlate, nidx, sizeof (uint32_t), ctf_lookup_idx_name); 857*6881a400Schristos 858*6881a400Schristos if (!idx) 859*6881a400Schristos { 860*6881a400Schristos ctf_dprintf ("%s not found in idx\n", symname); 861*6881a400Schristos return 0; 862*6881a400Schristos } 863*6881a400Schristos 864*6881a400Schristos /* Should be impossible, but be paranoid. */ 865*6881a400Schristos if ((idx - sxlate) > (ptrdiff_t) nidx) 8667d62b00eSchristos return (ctf_set_errno (fp, ECTF_CORRUPT)); 8677d62b00eSchristos 868*6881a400Schristos ctf_dprintf ("Symbol %lx (%s) is of type %x\n", symidx, symname, 869*6881a400Schristos symtypetab[*idx]); 870*6881a400Schristos return symtypetab[*idx]; 8717d62b00eSchristos } 8727d62b00eSchristos 873*6881a400Schristos /* Given a symbol name or (if NULL) symbol index, return the type of the 874*6881a400Schristos function or data object described by the corresponding entry in the symbol 875*6881a400Schristos table. We can only return symbols in read-only dicts and in dicts for which 876*6881a400Schristos ctf_link_shuffle_syms has been called to assign symbol indexes to symbol 877*6881a400Schristos names. */ 878*6881a400Schristos 879*6881a400Schristos static ctf_id_t 880*6881a400Schristos ctf_lookup_by_sym_or_name (ctf_dict_t *fp, unsigned long symidx, 881*6881a400Schristos const char *symname) 882*6881a400Schristos { 883*6881a400Schristos const ctf_sect_t *sp = &fp->ctf_symtab; 884*6881a400Schristos ctf_id_t type = 0; 885*6881a400Schristos int err = 0; 886*6881a400Schristos 887*6881a400Schristos /* Shuffled dynsymidx present? Use that. */ 888*6881a400Schristos if (fp->ctf_dynsymidx) 889*6881a400Schristos { 890*6881a400Schristos const ctf_link_sym_t *sym; 891*6881a400Schristos 892*6881a400Schristos if (symname) 893*6881a400Schristos ctf_dprintf ("Looking up type of object with symname %s in " 894*6881a400Schristos "writable dict symtypetab\n", symname); 895*6881a400Schristos else 896*6881a400Schristos ctf_dprintf ("Looking up type of object with symtab idx %lx in " 897*6881a400Schristos "writable dict symtypetab\n", symidx); 898*6881a400Schristos 899*6881a400Schristos /* The dict must be dynamic. */ 900*6881a400Schristos if (!ctf_assert (fp, fp->ctf_flags & LCTF_RDWR)) 901*6881a400Schristos return CTF_ERR; 902*6881a400Schristos 903*6881a400Schristos /* No name? Need to look it up. */ 904*6881a400Schristos if (!symname) 905*6881a400Schristos { 906*6881a400Schristos err = EINVAL; 907*6881a400Schristos if (symidx > fp->ctf_dynsymmax) 908*6881a400Schristos goto try_parent; 909*6881a400Schristos 910*6881a400Schristos sym = fp->ctf_dynsymidx[symidx]; 911*6881a400Schristos err = ECTF_NOTYPEDAT; 912*6881a400Schristos if (!sym || (sym->st_shndx != STT_OBJECT && sym->st_shndx != STT_FUNC)) 913*6881a400Schristos goto try_parent; 914*6881a400Schristos 915*6881a400Schristos if (!ctf_assert (fp, !sym->st_nameidx_set)) 916*6881a400Schristos return CTF_ERR; 917*6881a400Schristos symname = sym->st_name; 918*6881a400Schristos } 919*6881a400Schristos 920*6881a400Schristos if (fp->ctf_objthash == NULL 921*6881a400Schristos || ((type = (ctf_id_t) (uintptr_t) 922*6881a400Schristos ctf_dynhash_lookup (fp->ctf_objthash, symname)) == 0)) 923*6881a400Schristos { 924*6881a400Schristos if (fp->ctf_funchash == NULL 925*6881a400Schristos || ((type = (ctf_id_t) (uintptr_t) 926*6881a400Schristos ctf_dynhash_lookup (fp->ctf_funchash, symname)) == 0)) 927*6881a400Schristos goto try_parent; 928*6881a400Schristos } 929*6881a400Schristos 930*6881a400Schristos return type; 931*6881a400Schristos } 932*6881a400Schristos 933*6881a400Schristos /* Lookup by name in a dynamic dict: just do it directly. */ 934*6881a400Schristos if (symname && fp->ctf_flags & LCTF_RDWR) 935*6881a400Schristos { 936*6881a400Schristos if (fp->ctf_objthash == NULL 937*6881a400Schristos || ((type = (ctf_id_t) (uintptr_t) 938*6881a400Schristos ctf_dynhash_lookup (fp->ctf_objthash, symname)) == 0)) 939*6881a400Schristos { 940*6881a400Schristos if (fp->ctf_funchash == NULL 941*6881a400Schristos || ((type = (ctf_id_t) (uintptr_t) 942*6881a400Schristos ctf_dynhash_lookup (fp->ctf_funchash, symname)) == 0)) 943*6881a400Schristos goto try_parent; 944*6881a400Schristos } 945*6881a400Schristos return type; 946*6881a400Schristos } 947*6881a400Schristos 948*6881a400Schristos err = ECTF_NOSYMTAB; 949*6881a400Schristos if (sp->cts_data == NULL) 950*6881a400Schristos goto try_parent; 951*6881a400Schristos 952*6881a400Schristos /* This covers both out-of-range lookups and a dynamic dict which hasn't been 953*6881a400Schristos shuffled yet. */ 954*6881a400Schristos err = EINVAL; 955*6881a400Schristos if (symname == NULL && symidx >= fp->ctf_nsyms) 956*6881a400Schristos goto try_parent; 957*6881a400Schristos 958*6881a400Schristos if (fp->ctf_objtidx_names) 959*6881a400Schristos { 960*6881a400Schristos if ((type = ctf_try_lookup_indexed (fp, symidx, symname, 0)) == CTF_ERR) 961*6881a400Schristos return CTF_ERR; /* errno is set for us. */ 962*6881a400Schristos } 963*6881a400Schristos if (type == 0 && fp->ctf_funcidx_names) 964*6881a400Schristos { 965*6881a400Schristos if ((type = ctf_try_lookup_indexed (fp, symidx, symname, 1)) == CTF_ERR) 966*6881a400Schristos return CTF_ERR; /* errno is set for us. */ 967*6881a400Schristos } 968*6881a400Schristos if (type != 0) 969*6881a400Schristos return type; 970*6881a400Schristos 971*6881a400Schristos err = ECTF_NOTYPEDAT; 972*6881a400Schristos if (fp->ctf_objtidx_names && fp->ctf_funcidx_names) 973*6881a400Schristos goto try_parent; 974*6881a400Schristos 975*6881a400Schristos /* Table must be nonindexed. */ 976*6881a400Schristos 977*6881a400Schristos ctf_dprintf ("Looking up object type %lx in 1:1 dict symtypetab\n", symidx); 978*6881a400Schristos 979*6881a400Schristos if (symname != NULL) 980*6881a400Schristos if ((symidx = ctf_lookup_symbol_idx (fp, symname)) == (unsigned long) -1) 981*6881a400Schristos goto try_parent; 982*6881a400Schristos 983*6881a400Schristos if (fp->ctf_sxlate[symidx] == -1u) 984*6881a400Schristos goto try_parent; 985*6881a400Schristos 986*6881a400Schristos type = *(uint32_t *) ((uintptr_t) fp->ctf_buf + fp->ctf_sxlate[symidx]); 987*6881a400Schristos 988*6881a400Schristos if (type == 0) 989*6881a400Schristos goto try_parent; 990*6881a400Schristos 991*6881a400Schristos return type; 992*6881a400Schristos try_parent: 993*6881a400Schristos if (fp->ctf_parent) 994*6881a400Schristos { 995*6881a400Schristos ctf_id_t ret = ctf_lookup_by_sym_or_name (fp->ctf_parent, symidx, 996*6881a400Schristos symname); 997*6881a400Schristos if (ret == CTF_ERR) 998*6881a400Schristos ctf_set_errno (fp, ctf_errno (fp->ctf_parent)); 999*6881a400Schristos return ret; 1000*6881a400Schristos } 1001*6881a400Schristos else 1002*6881a400Schristos return (ctf_set_errno (fp, err)); 1003*6881a400Schristos } 1004*6881a400Schristos 1005*6881a400Schristos /* Given a symbol table index, return the type of the function or data object 1006*6881a400Schristos described by the corresponding entry in the symbol table. */ 1007*6881a400Schristos ctf_id_t 1008*6881a400Schristos ctf_lookup_by_symbol (ctf_dict_t *fp, unsigned long symidx) 1009*6881a400Schristos { 1010*6881a400Schristos return ctf_lookup_by_sym_or_name (fp, symidx, NULL); 1011*6881a400Schristos } 1012*6881a400Schristos 1013*6881a400Schristos /* Given a symbol name, return the type of the function or data object described 1014*6881a400Schristos by the corresponding entry in the symbol table. */ 1015*6881a400Schristos ctf_id_t 1016*6881a400Schristos ctf_lookup_by_symbol_name (ctf_dict_t *fp, const char *symname) 1017*6881a400Schristos { 1018*6881a400Schristos return ctf_lookup_by_sym_or_name (fp, 0, symname); 1019*6881a400Schristos } 1020*6881a400Schristos 1021*6881a400Schristos /* Given a symbol table index, return the info for the function described 1022*6881a400Schristos by the corresponding entry in the symbol table, which may be a function 1023*6881a400Schristos symbol or may be a data symbol that happens to be a function pointer. */ 1024*6881a400Schristos 1025*6881a400Schristos int 1026*6881a400Schristos ctf_func_info (ctf_dict_t *fp, unsigned long symidx, ctf_funcinfo_t *fip) 1027*6881a400Schristos { 1028*6881a400Schristos ctf_id_t type; 1029*6881a400Schristos 1030*6881a400Schristos if ((type = ctf_lookup_by_symbol (fp, symidx)) == CTF_ERR) 1031*6881a400Schristos return -1; /* errno is set for us. */ 1032*6881a400Schristos 1033*6881a400Schristos if (ctf_type_kind (fp, type) != CTF_K_FUNCTION) 1034*6881a400Schristos return (ctf_set_errno (fp, ECTF_NOTFUNC)); 1035*6881a400Schristos 1036*6881a400Schristos return ctf_func_type_info (fp, type, fip); 10377d62b00eSchristos } 10387d62b00eSchristos 10397d62b00eSchristos /* Given a symbol table index, return the arguments for the function described 10407d62b00eSchristos by the corresponding entry in the symbol table. */ 10417d62b00eSchristos 10427d62b00eSchristos int 1043*6881a400Schristos ctf_func_args (ctf_dict_t *fp, unsigned long symidx, uint32_t argc, 10447d62b00eSchristos ctf_id_t *argv) 10457d62b00eSchristos { 1046*6881a400Schristos ctf_id_t type; 10477d62b00eSchristos 1048*6881a400Schristos if ((type = ctf_lookup_by_symbol (fp, symidx)) == CTF_ERR) 10497d62b00eSchristos return -1; /* errno is set for us. */ 10507d62b00eSchristos 1051*6881a400Schristos if (ctf_type_kind (fp, type) != CTF_K_FUNCTION) 1052*6881a400Schristos return (ctf_set_errno (fp, ECTF_NOTFUNC)); 10537d62b00eSchristos 1054*6881a400Schristos return ctf_func_type_args (fp, type, argc, argv); 10557d62b00eSchristos } 1056