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