libctf, include: support unnamed structure members better
[deliverable/binutils-gdb.git] / libctf / ctf-lookup.c
CommitLineData
12a0b67d 1/* Symbol, variable and name lookup.
250d07de 2 Copyright (C) 2019-2021 Free Software Foundation, Inc.
47d546f4
NA
3
4 This file is part of libctf.
5
6 libctf is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 See the GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; see the file COPYING. If not see
18 <http://www.gnu.org/licenses/>. */
19
20#include <ctf-impl.h>
21#include <elf.h>
22#include <string.h>
1136c379 23#include <assert.h>
47d546f4 24
b437bfe0
NA
25/* Compare the given input string and length against a table of known C storage
26 qualifier keywords. We just ignore these in ctf_lookup_by_name, below. To
27 do this quickly, we use a pre-computed Perfect Hash Function similar to the
28 technique originally described in the classic paper:
29
30 R.J. Cichelli, "Minimal Perfect Hash Functions Made Simple",
31 Communications of the ACM, Volume 23, Issue 1, January 1980, pp. 17-19.
32
33 For an input string S of length N, we use hash H = S[N - 1] + N - 105, which
34 for the current set of qualifiers yields a unique H in the range [0 .. 20].
35 The hash can be modified when the keyword set changes as necessary. We also
36 store the length of each keyword and check it prior to the final strcmp().
37
38 TODO: just use gperf. */
39
40static int
41isqualifier (const char *s, size_t len)
42{
43 static const struct qual
44 {
45 const char *q_name;
46 size_t q_len;
47 } qhash[] = {
48 {"static", 6}, {"", 0}, {"", 0}, {"", 0},
49 {"volatile", 8}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
50 {"", 0}, {"auto", 4}, {"extern", 6}, {"", 0}, {"", 0},
51 {"", 0}, {"", 0}, {"const", 5}, {"register", 8},
52 {"", 0}, {"restrict", 8}, {"_Restrict", 9}
53 };
54
55 int h = s[len - 1] + (int) len - 105;
56 const struct qual *qp = &qhash[h];
57
58 return (h >= 0 && (size_t) h < sizeof (qhash) / sizeof (qhash[0])
59 && (size_t) len == qp->q_len &&
60 strncmp (qp->q_name, s, qp->q_len) == 0);
61}
62
63/* Attempt to convert the given C type name into the corresponding CTF type ID.
64 It is not possible to do complete and proper conversion of type names
65 without implementing a more full-fledged parser, which is necessary to
66 handle things like types that are function pointers to functions that
67 have arguments that are function pointers, and fun stuff like that.
68 Instead, this function implements a very simple conversion algorithm that
69 finds the things that we actually care about: structs, unions, enums,
70 integers, floats, typedefs, and pointers to any of these named types. */
71
72ctf_id_t
139633c3 73ctf_lookup_by_name (ctf_dict_t *fp, const char *name)
b437bfe0
NA
74{
75 static const char delimiters[] = " \t\n\r\v\f*";
76
77 const ctf_lookup_t *lp;
78 const char *p, *q, *end;
79 ctf_id_t type = 0;
80 ctf_id_t ntype, ptype;
81
82 if (name == NULL)
83 return (ctf_set_errno (fp, EINVAL));
84
85 for (p = name, end = name + strlen (name); *p != '\0'; p = q)
86 {
734c8942 87 while (isspace ((int) *p))
b437bfe0
NA
88 p++; /* Skip leading whitespace. */
89
90 if (p == end)
91 break;
92
93 if ((q = strpbrk (p + 1, delimiters)) == NULL)
94 q = end; /* Compare until end. */
95
96 if (*p == '*')
97 {
98 /* Find a pointer to type by looking in fp->ctf_ptrtab.
99 If we can't find a pointer to the given type, see if
100 we can compute a pointer to the type resulting from
101 resolving the type down to its base type and use
102 that instead. This helps with cases where the CTF
103 data includes "struct foo *" but not "foo_t *" and
104 the user tries to access "foo_t *" in the debugger.
105
139633c3 106 TODO need to handle parent dicts too. */
b437bfe0
NA
107
108 ntype = fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX (fp, type)];
109 if (ntype == 0)
110 {
111 ntype = ctf_type_resolve_unsliced (fp, type);
112 if (ntype == CTF_ERR
113 || (ntype =
114 fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX (fp, ntype)]) == 0)
115 {
116 (void) ctf_set_errno (fp, ECTF_NOTYPE);
117 goto err;
118 }
119 }
120
121 type = LCTF_INDEX_TO_TYPE (fp, ntype, (fp->ctf_flags & LCTF_CHILD));
122
123 q = p + 1;
124 continue;
125 }
126
127 if (isqualifier (p, (size_t) (q - p)))
128 continue; /* Skip qualifier keyword. */
129
130 for (lp = fp->ctf_lookups; lp->ctl_prefix != NULL; lp++)
131 {
132 /* TODO: This is not MT-safe. */
133 if ((lp->ctl_prefix[0] == '\0' ||
134 strncmp (p, lp->ctl_prefix, (size_t) (q - p)) == 0) &&
135 (size_t) (q - p) >= lp->ctl_len)
136 {
734c8942 137 for (p += lp->ctl_len; isspace ((int) *p); p++)
b437bfe0
NA
138 continue; /* Skip prefix and next whitespace. */
139
140 if ((q = strchr (p, '*')) == NULL)
141 q = end; /* Compare until end. */
142
734c8942 143 while (isspace ((int) q[-1]))
b437bfe0
NA
144 q--; /* Exclude trailing whitespace. */
145
146 /* Expand and/or allocate storage for a slice of the name, then
147 copy it in. */
148
149 if (fp->ctf_tmp_typeslicelen >= (size_t) (q - p) + 1)
150 {
151 memcpy (fp->ctf_tmp_typeslice, p, (size_t) (q - p));
152 fp->ctf_tmp_typeslice[(size_t) (q - p)] = '\0';
153 }
154 else
155 {
156 free (fp->ctf_tmp_typeslice);
942d35f7 157 fp->ctf_tmp_typeslice = xstrndup (p, (size_t) (q - p));
b437bfe0
NA
158 if (fp->ctf_tmp_typeslice == NULL)
159 {
160 (void) ctf_set_errno (fp, ENOMEM);
161 return CTF_ERR;
162 }
163 }
164
676c3ecb
NA
165 if ((type = ctf_lookup_by_rawhash (fp, lp->ctl_hash,
166 fp->ctf_tmp_typeslice)) == 0)
b437bfe0
NA
167 {
168 (void) ctf_set_errno (fp, ECTF_NOTYPE);
169 goto err;
170 }
171
172 break;
173 }
174 }
175
176 if (lp->ctl_prefix == NULL)
177 {
178 (void) ctf_set_errno (fp, ECTF_NOTYPE);
179 goto err;
180 }
181 }
182
183 if (*p != '\0' || type == 0)
184 return (ctf_set_errno (fp, ECTF_SYNTAX));
185
186 return type;
187
188err:
189 if (fp->ctf_parent != NULL
190 && (ptype = ctf_lookup_by_name (fp->ctf_parent, name)) != CTF_ERR)
191 return ptype;
192
193 return CTF_ERR;
194}
195
1136c379
NA
196/* Return the pointer to the internal CTF type data corresponding to the
197 given type ID. If the ID is invalid, the function returns NULL.
198 This function is not exported outside of the library. */
199
200const ctf_type_t *
201ctf_lookup_by_id (ctf_dict_t **fpp, ctf_id_t type)
b437bfe0 202{
1136c379
NA
203 ctf_dict_t *fp = *fpp; /* Caller passes in starting CTF dict. */
204 ctf_id_t idx;
205
206 if ((fp = ctf_get_dict (fp, type)) == NULL)
207 {
208 (void) ctf_set_errno (*fpp, ECTF_NOPARENT);
209 return NULL;
210 }
211
212 /* If this dict is writable, check for a dynamic type. */
213
214 if (fp->ctf_flags & LCTF_RDWR)
215 {
216 ctf_dtdef_t *dtd;
217
218 if ((dtd = ctf_dynamic_type (fp, type)) != NULL)
219 {
220 *fpp = fp;
221 return &dtd->dtd_data;
222 }
223 (void) ctf_set_errno (*fpp, ECTF_BADID);
224 return NULL;
225 }
226
227 /* Check for a type in the static portion. */
228
229 idx = LCTF_TYPE_TO_INDEX (fp, type);
230 if (idx > 0 && (unsigned long) idx <= fp->ctf_typemax)
231 {
232 *fpp = fp; /* Function returns ending CTF dict. */
233 return (LCTF_INDEX_TO_TYPEPTR (fp, idx));
234 }
235
236 (void) ctf_set_errno (*fpp, ECTF_BADID);
237 return NULL;
238}
239
240typedef struct ctf_lookup_idx_key
241{
242 ctf_dict_t *clik_fp;
243 const char *clik_name;
244 uint32_t *clik_names;
245} ctf_lookup_idx_key_t;
b437bfe0
NA
246
247/* A bsearch function for variable names. */
248
249static int
1136c379 250ctf_lookup_var (const void *key_, const void *lookup_)
b437bfe0 251{
1136c379
NA
252 const ctf_lookup_idx_key_t *key = key_;
253 const ctf_varent_t *lookup = lookup_;
b437bfe0 254
1136c379 255 return (strcmp (key->clik_name, ctf_strptr (key->clik_fp, lookup->ctv_name)));
b437bfe0
NA
256}
257
258/* Given a variable name, return the type of the variable with that name. */
259
260ctf_id_t
139633c3 261ctf_lookup_variable (ctf_dict_t *fp, const char *name)
b437bfe0
NA
262{
263 ctf_varent_t *ent;
1136c379 264 ctf_lookup_idx_key_t key = { fp, name, NULL };
b437bfe0
NA
265
266 /* This array is sorted, so we can bsearch for it. */
267
268 ent = bsearch (&key, fp->ctf_vars, fp->ctf_nvars, sizeof (ctf_varent_t),
269 ctf_lookup_var);
270
271 if (ent == NULL)
272 {
273 if (fp->ctf_parent != NULL)
274 return ctf_lookup_variable (fp->ctf_parent, name);
275
276 return (ctf_set_errno (fp, ECTF_NOTYPEDAT));
277 }
278
279 return ent->ctv_type;
280}
281
1136c379
NA
282typedef struct ctf_symidx_sort_arg_cb
283{
284 ctf_dict_t *fp;
285 uint32_t *names;
286} ctf_symidx_sort_arg_cb_t;
287
288static int
289sort_symidx_by_name (const void *one_, const void *two_, void *arg_)
290{
291 const uint32_t *one = one_;
292 const uint32_t *two = two_;
293 ctf_symidx_sort_arg_cb_t *arg = arg_;
294
295 return (strcmp (ctf_strptr (arg->fp, arg->names[*one]),
296 ctf_strptr (arg->fp, arg->names[*two])));
297}
298
299/* Sort a symbol index section by name. Takes a 1:1 mapping of names to the
300 corresponding symbol table. Returns a lexicographically sorted array of idx
301 indexes (and thus, of indexes into the corresponding func info / data object
302 section). */
303
304static uint32_t *
305ctf_symidx_sort (ctf_dict_t *fp, uint32_t *idx, size_t *nidx,
306 size_t len)
307{
308 uint32_t *sorted;
309 size_t i;
310
311 if ((sorted = malloc (len)) == NULL)
312 {
313 ctf_set_errno (fp, ENOMEM);
314 return NULL;
315 }
316
317 *nidx = len / sizeof (uint32_t);
318 for (i = 0; i < *nidx; i++)
319 sorted[i] = i;
320
321 if (!(fp->ctf_header->cth_flags & CTF_F_IDXSORTED))
322 {
323 ctf_symidx_sort_arg_cb_t arg = { fp, idx };
324 ctf_dprintf ("Index section unsorted: sorting.");
325 ctf_qsort_r (sorted, *nidx, sizeof (uint32_t), sort_symidx_by_name, &arg);
326 fp->ctf_header->cth_flags |= CTF_F_IDXSORTED;
327 }
328
329 return sorted;
330}
331
332/* Given a symbol index, return the name of that symbol from the table provided
333 by ctf_link_shuffle_syms, or failing that from the secondary string table, or
334 the null string. */
b437bfe0 335const char *
139633c3 336ctf_lookup_symbol_name (ctf_dict_t *fp, unsigned long symidx)
b437bfe0
NA
337{
338 const ctf_sect_t *sp = &fp->ctf_symtab;
1136c379
NA
339 ctf_link_sym_t sym;
340 int err;
b437bfe0 341
1136c379 342 if (fp->ctf_dynsymidx)
b437bfe0 343 {
1136c379
NA
344 err = EINVAL;
345 if (symidx > fp->ctf_dynsymmax)
346 goto try_parent;
347
348 ctf_link_sym_t *symp = fp->ctf_dynsymidx[symidx];
349
350 if (!symp)
351 goto try_parent;
352
353 return symp->st_name;
b437bfe0
NA
354 }
355
1136c379
NA
356 err = ECTF_NOSYMTAB;
357 if (sp->cts_data == NULL)
358 goto try_parent;
359
b437bfe0 360 if (symidx >= fp->ctf_nsyms)
1136c379
NA
361 goto try_parent;
362
363 switch (sp->cts_entsize)
b437bfe0 364 {
1136c379
NA
365 case sizeof (Elf64_Sym):
366 {
367 const Elf64_Sym *symp = (Elf64_Sym *) sp->cts_data + symidx;
368 ctf_elf64_to_link_sym (fp, &sym, symp, symidx);
369 }
370 break;
371 case sizeof (Elf32_Sym):
372 {
373 const Elf32_Sym *symp = (Elf32_Sym *) sp->cts_data + symidx;
374 ctf_elf32_to_link_sym (fp, &sym, symp, symidx);
375 }
376 break;
377 default:
378 ctf_set_errno (fp, ECTF_SYMTAB);
b437bfe0
NA
379 return _CTF_NULLSTR;
380 }
381
1136c379 382 assert (!sym.st_nameidx_set);
b437bfe0 383
1136c379 384 return sym.st_name;
b437bfe0 385
1136c379
NA
386 try_parent:
387 if (fp->ctf_parent)
388 return ctf_lookup_symbol_name (fp->ctf_parent, symidx);
389 else
390 {
391 ctf_set_errno (fp, err);
392 return _CTF_NULLSTR;
393 }
b437bfe0
NA
394}
395
1136c379
NA
396/* Iterate over all symbols with types: if FUNC, function symbols, otherwise,
397 data symbols. The name argument is not optional. The return order is
398 arbitrary, though is likely to be in symbol index or name order. You can
399 change the value of 'functions' in the middle of iteration over non-dynamic
400 dicts, but doing so on dynamic dicts will fail. (This is probably not very
401 useful, but there is no reason to prohibit it.) */
b437bfe0
NA
402
403ctf_id_t
1136c379
NA
404ctf_symbol_next (ctf_dict_t *fp, ctf_next_t **it, const char **name,
405 int functions)
b437bfe0 406{
1136c379
NA
407 ctf_id_t sym;
408 ctf_next_t *i = *it;
409 int err;
b437bfe0 410
1136c379
NA
411 if (!i)
412 {
413 if ((i = ctf_next_create ()) == NULL)
414 return ctf_set_errno (fp, ENOMEM);
b437bfe0 415
1136c379
NA
416 i->cu.ctn_fp = fp;
417 i->ctn_iter_fun = (void (*) (void)) ctf_symbol_next;
418 i->ctn_n = 0;
419 *it = i;
420 }
421
422 if ((void (*) (void)) ctf_symbol_next != i->ctn_iter_fun)
423 return (ctf_set_errno (fp, ECTF_NEXT_WRONGFUN));
b437bfe0 424
1136c379
NA
425 if (fp != i->cu.ctn_fp)
426 return (ctf_set_errno (fp, ECTF_NEXT_WRONGFP));
427
428 /* We intentionally use raw access, not ctf_lookup_by_symbol, to avoid
429 incurring additional sorting cost for unsorted symtypetabs coming from the
430 compiler, to allow ctf_symbol_next to work in the absence of a symtab, and
431 finally because it's easier to work out what the name of each symbol is if
432 we do that. */
433
434 if (fp->ctf_flags & LCTF_RDWR)
b437bfe0 435 {
1136c379
NA
436 ctf_dynhash_t *dynh = functions ? fp->ctf_funchash : fp->ctf_objthash;
437 void *dyn_name = NULL, *dyn_value = NULL;
438
439 if (!dynh)
440 {
441 ctf_next_destroy (i);
442 return (ctf_set_errno (fp, ECTF_NEXT_END));
443 }
444
6c3a3877 445 err = ctf_dynhash_next (dynh, &i->ctn_next, &dyn_name, &dyn_value);
1136c379
NA
446 /* This covers errors and also end-of-iteration. */
447 if (err != 0)
448 {
449 ctf_next_destroy (i);
450 *it = NULL;
451 return ctf_set_errno (fp, err);
452 }
453
454 *name = dyn_name;
455 sym = (ctf_id_t) (uintptr_t) dyn_value;
b437bfe0 456 }
1136c379
NA
457 else if ((!functions && fp->ctf_objtidx_names) ||
458 (functions && fp->ctf_funcidx_names))
b437bfe0 459 {
1136c379
NA
460 ctf_header_t *hp = fp->ctf_header;
461 uint32_t *idx = functions ? fp->ctf_funcidx_names : fp->ctf_objtidx_names;
462 uint32_t *tab;
463 size_t len;
464
465 if (functions)
466 {
467 len = (hp->cth_varoff - hp->cth_funcidxoff) / sizeof (uint32_t);
468 tab = (uint32_t *) (fp->ctf_buf + hp->cth_funcoff);
469 }
470 else
471 {
472 len = (hp->cth_funcidxoff - hp->cth_objtidxoff) / sizeof (uint32_t);
473 tab = (uint32_t *) (fp->ctf_buf + hp->cth_objtoff);
474 }
475
476 do
477 {
478 if (i->ctn_n >= len)
479 goto end;
480
481 *name = ctf_strptr (fp, idx[i->ctn_n]);
482 sym = tab[i->ctn_n++];
483 } while (sym == -1u || sym == 0);
b437bfe0 484 }
1136c379
NA
485 else
486 {
487 /* Skip over pads in ctf_xslate, padding for typeless symbols in the
488 symtypetab itself, and symbols in the wrong table. */
489 for (; i->ctn_n < fp->ctf_nsyms; i->ctn_n++)
490 {
491 ctf_header_t *hp = fp->ctf_header;
b437bfe0 492
1136c379
NA
493 if (fp->ctf_sxlate[i->ctn_n] == -1u)
494 continue;
b437bfe0 495
1136c379 496 sym = *(uint32_t *) ((uintptr_t) fp->ctf_buf + fp->ctf_sxlate[i->ctn_n]);
b437bfe0 497
1136c379
NA
498 if (sym == 0)
499 continue;
500
501 if (functions)
502 {
503 if (fp->ctf_sxlate[i->ctn_n] >= hp->cth_funcoff
504 && fp->ctf_sxlate[i->ctn_n] < hp->cth_objtidxoff)
505 break;
506 }
507 else
508 {
509 if (fp->ctf_sxlate[i->ctn_n] >= hp->cth_objtoff
510 && fp->ctf_sxlate[i->ctn_n] < hp->cth_funcoff)
511 break;
512 }
513 }
514
515 if (i->ctn_n >= fp->ctf_nsyms)
516 goto end;
517
518 *name = ctf_lookup_symbol_name (fp, i->ctn_n++);
519 }
520
521 return sym;
522
523 end:
524 ctf_next_destroy (i);
525 *it = NULL;
526 return (ctf_set_errno (fp, ECTF_NEXT_END));
b437bfe0
NA
527}
528
1136c379
NA
529/* A bsearch function for function and object index names. */
530
531static int
532ctf_lookup_idx_name (const void *key_, const void *idx_)
688d28f6 533{
1136c379
NA
534 const ctf_lookup_idx_key_t *key = key_;
535 const uint32_t *idx = idx_;
688d28f6 536
1136c379 537 return (strcmp (key->clik_name, ctf_strptr (key->clik_fp, key->clik_names[*idx])));
688d28f6
NA
538}
539
1136c379
NA
540/* Given a symbol number, look up that symbol in the function or object
541 index table (which must exist). Return 0 if not found there (or pad). */
47d546f4 542
1136c379
NA
543static ctf_id_t
544ctf_try_lookup_indexed (ctf_dict_t *fp, unsigned long symidx, int is_function)
47d546f4 545{
1136c379
NA
546 const char *symname = ctf_lookup_symbol_name (fp, symidx);
547 struct ctf_header *hp = fp->ctf_header;
548 uint32_t *symtypetab;
549 uint32_t *names;
550 uint32_t *sxlate;
551 size_t nidx;
47d546f4 552
1136c379
NA
553 ctf_dprintf ("Looking up type of object with symtab idx %lx (%s) in "
554 "indexed symtypetab\n", symidx, symname);
47d546f4 555
1136c379
NA
556 if (symname[0] == '\0')
557 return -1; /* errno is set for us. */
47d546f4 558
1136c379 559 if (is_function)
47d546f4 560 {
1136c379 561 if (!fp->ctf_funcidx_sxlate)
47d546f4 562 {
1136c379
NA
563 if ((fp->ctf_funcidx_sxlate
564 = ctf_symidx_sort (fp, (uint32_t *)
565 (fp->ctf_buf + hp->cth_funcidxoff),
566 &fp->ctf_nfuncidx,
567 hp->cth_varoff - hp->cth_funcidxoff))
568 == NULL)
569 {
570 ctf_err_warn (fp, 0, 0, _("cannot sort function symidx"));
571 return -1; /* errno is set for us. */
572 }
47d546f4 573 }
1136c379
NA
574 symtypetab = (uint32_t *) (fp->ctf_buf + hp->cth_funcoff);
575 sxlate = fp->ctf_funcidx_sxlate;
576 names = fp->ctf_funcidx_names;
577 nidx = fp->ctf_nfuncidx;
47d546f4 578 }
1136c379
NA
579 else
580 {
581 if (!fp->ctf_objtidx_sxlate)
582 {
583 if ((fp->ctf_objtidx_sxlate
584 = ctf_symidx_sort (fp, (uint32_t *)
585 (fp->ctf_buf + hp->cth_objtidxoff),
586 &fp->ctf_nobjtidx,
587 hp->cth_funcidxoff - hp->cth_objtidxoff))
588 == NULL)
589 {
590 ctf_err_warn (fp, 0, 0, _("cannot sort object symidx"));
591 return -1; /* errno is set for us. */
592 }
593 }
676c3ecb 594
1136c379
NA
595 symtypetab = (uint32_t *) (fp->ctf_buf + hp->cth_objtoff);
596 sxlate = fp->ctf_objtidx_sxlate;
597 names = fp->ctf_objtidx_names;
598 nidx = fp->ctf_nobjtidx;
599 }
676c3ecb 600
1136c379
NA
601 ctf_lookup_idx_key_t key = { fp, symname, names };
602 uint32_t *idx;
603
604 idx = bsearch (&key, sxlate, nidx, sizeof (uint32_t), ctf_lookup_idx_name);
605
606 if (!idx)
676c3ecb 607 {
1136c379
NA
608 ctf_dprintf ("%s not found in idx\n", symname);
609 return 0;
676c3ecb
NA
610 }
611
1136c379
NA
612 /* Should be impossible, but be paranoid. */
613 if ((idx - sxlate) > (ptrdiff_t) nidx)
614 return (ctf_set_errno (fp, ECTF_CORRUPT));
615
616 ctf_dprintf ("Symbol %lx (%s) is of type %x\n", symidx, symname,
617 symtypetab[*idx]);
618 return symtypetab[*idx];
47d546f4
NA
619}
620
1136c379
NA
621/* Given a symbol table index, return the type of the function or data object
622 described by the corresponding entry in the symbol table. We can only return
623 symbols in read-only dicts and in dicts for which ctf_link_shuffle_syms has
624 been called to assign symbol indexes to symbol names. */
b437bfe0 625
1136c379
NA
626ctf_id_t
627ctf_lookup_by_symbol (ctf_dict_t *fp, unsigned long symidx)
b437bfe0
NA
628{
629 const ctf_sect_t *sp = &fp->ctf_symtab;
1136c379
NA
630 ctf_id_t type = 0;
631 int err = 0;
632
633 /* Shuffled dynsymidx present? Use that. */
634 if (fp->ctf_dynsymidx)
635 {
636 const ctf_link_sym_t *sym;
637
638 ctf_dprintf ("Looking up type of object with symtab idx %lx in "
639 "writable dict symtypetab\n", symidx);
640
641 /* The dict must be dynamic. */
642 if (!ctf_assert (fp, fp->ctf_flags & LCTF_RDWR))
643 return CTF_ERR;
644
645 err = EINVAL;
646 if (symidx > fp->ctf_dynsymmax)
647 goto try_parent;
648
649 sym = fp->ctf_dynsymidx[symidx];
650 err = ECTF_NOTYPEDAT;
651 if (!sym || (sym->st_shndx != STT_OBJECT && sym->st_shndx != STT_FUNC))
652 goto try_parent;
653
654 if (!ctf_assert (fp, !sym->st_nameidx_set))
655 return CTF_ERR;
656
657 if (fp->ctf_objthash == NULL
658 || ((type = (ctf_id_t) (uintptr_t)
659 ctf_dynhash_lookup (fp->ctf_objthash, sym->st_name)) == 0))
660 {
661 if (fp->ctf_funchash == NULL
662 || ((type = (ctf_id_t) (uintptr_t)
663 ctf_dynhash_lookup (fp->ctf_funchash, sym->st_name)) == 0))
664 goto try_parent;
665 }
666
667 return type;
668 }
b437bfe0 669
1136c379 670 err = ECTF_NOSYMTAB;
b437bfe0 671 if (sp->cts_data == NULL)
1136c379 672 goto try_parent;
b437bfe0 673
1136c379
NA
674 /* This covers both out-of-range lookups and a dynamic dict which hasn't been
675 shuffled yet. */
676 err = EINVAL;
b437bfe0 677 if (symidx >= fp->ctf_nsyms)
1136c379 678 goto try_parent;
b437bfe0 679
1136c379 680 if (fp->ctf_objtidx_names)
b437bfe0 681 {
1136c379
NA
682 if ((type = ctf_try_lookup_indexed (fp, symidx, 0)) == CTF_ERR)
683 return CTF_ERR; /* errno is set for us. */
b437bfe0 684 }
1136c379 685 if (type == 0 && fp->ctf_funcidx_names)
b437bfe0 686 {
1136c379
NA
687 if ((type = ctf_try_lookup_indexed (fp, symidx, 1)) == CTF_ERR)
688 return CTF_ERR; /* errno is set for us. */
b437bfe0 689 }
1136c379
NA
690 if (type != 0)
691 return type;
692
693 err = ECTF_NOTYPEDAT;
694 if (fp->ctf_objtidx_names && fp->ctf_funcidx_names)
695 goto try_parent;
696
697 /* Table must be nonindexed. */
698
699 ctf_dprintf ("Looking up object type %lx in 1:1 dict symtypetab\n", symidx);
b437bfe0
NA
700
701 if (fp->ctf_sxlate[symidx] == -1u)
1136c379
NA
702 goto try_parent;
703
704 type = *(uint32_t *) ((uintptr_t) fp->ctf_buf + fp->ctf_sxlate[symidx]);
b437bfe0 705
1136c379
NA
706 if (type == 0)
707 goto try_parent;
b437bfe0 708
1136c379
NA
709 return type;
710 try_parent:
711 if (fp->ctf_parent)
712 return ctf_lookup_by_symbol (fp->ctf_parent, symidx);
713 else
714 return (ctf_set_errno (fp, err));
715}
b437bfe0 716
1136c379
NA
717/* Given a symbol table index, return the info for the function described
718 by the corresponding entry in the symbol table, which may be a function
719 symbol or may be a data symbol that happens to be a function pointer. */
b437bfe0 720
1136c379
NA
721int
722ctf_func_info (ctf_dict_t *fp, unsigned long symidx, ctf_funcinfo_t *fip)
723{
724 ctf_id_t type;
b437bfe0 725
1136c379
NA
726 if ((type = ctf_lookup_by_symbol (fp, symidx)) == CTF_ERR)
727 return -1; /* errno is set for us. */
b437bfe0 728
1136c379
NA
729 if (ctf_type_kind (fp, type) != CTF_K_FUNCTION)
730 return (ctf_set_errno (fp, ECTF_NOTFUNC));
b437bfe0 731
1136c379 732 return ctf_func_type_info (fp, type, fip);
b437bfe0
NA
733}
734
735/* Given a symbol table index, return the arguments for the function described
736 by the corresponding entry in the symbol table. */
737
738int
139633c3 739ctf_func_args (ctf_dict_t *fp, unsigned long symidx, uint32_t argc,
1136c379 740 ctf_id_t *argv)
b437bfe0 741{
1136c379 742 ctf_id_t type;
b437bfe0 743
1136c379
NA
744 if ((type = ctf_lookup_by_symbol (fp, symidx)) == CTF_ERR)
745 return -1; /* errno is set for us. */
b437bfe0 746
1136c379
NA
747 if (ctf_type_kind (fp, type) != CTF_K_FUNCTION)
748 return (ctf_set_errno (fp, ECTF_NOTFUNC));
b437bfe0 749
1136c379 750 return ctf_func_type_args (fp, type, argc, argv);
b437bfe0 751}
This page took 0.139941 seconds and 4 git commands to generate.