1 /* Symbol, variable and name lookup.
2 Copyright (C) 2019-2022 Free Software Foundation, Inc.
4 This file is part of libctf.
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
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.
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/>. */
25 /* Grow the pptrtab so that it is at least NEW_LEN long. */
27 grow_pptrtab (ctf_dict_t
*fp
, size_t new_len
)
29 uint32_t *new_pptrtab
;
31 if ((new_pptrtab
= realloc (fp
->ctf_pptrtab
, sizeof (uint32_t)
33 return (ctf_set_errno (fp
, ENOMEM
));
35 fp
->ctf_pptrtab
= new_pptrtab
;
37 memset (fp
->ctf_pptrtab
+ fp
->ctf_pptrtab_len
, 0,
38 sizeof (uint32_t) * (new_len
- fp
->ctf_pptrtab_len
));
40 fp
->ctf_pptrtab_len
= new_len
;
44 /* Update entries in the pptrtab that relate to types newly added in the
47 refresh_pptrtab (ctf_dict_t
*fp
, ctf_dict_t
*pfp
)
50 for (i
= fp
->ctf_pptrtab_typemax
; i
<= fp
->ctf_typemax
; i
++)
52 ctf_id_t type
= LCTF_INDEX_TO_TYPE (fp
, i
, 1);
55 if (ctf_type_kind (fp
, type
) != CTF_K_POINTER
)
58 reffed_type
= ctf_type_reference (fp
, type
);
60 if (LCTF_TYPE_ISPARENT (fp
, reffed_type
))
62 uint32_t idx
= LCTF_TYPE_TO_INDEX (fp
, reffed_type
);
64 /* Guard against references to invalid types. No need to consider
65 the CTF dict corrupt in this case: this pointer just can't be a
66 pointer to any type we know about. */
67 if (idx
<= pfp
->ctf_typemax
)
69 if (idx
>= fp
->ctf_pptrtab_len
70 && grow_pptrtab (fp
, pfp
->ctf_ptrtab_len
) < 0)
71 return -1; /* errno is set for us. */
73 fp
->ctf_pptrtab
[idx
] = i
;
78 fp
->ctf_pptrtab_typemax
= fp
->ctf_typemax
;
83 /* Compare the given input string and length against a table of known C storage
84 qualifier keywords. We just ignore these in ctf_lookup_by_name, below. To
85 do this quickly, we use a pre-computed Perfect Hash Function similar to the
86 technique originally described in the classic paper:
88 R.J. Cichelli, "Minimal Perfect Hash Functions Made Simple",
89 Communications of the ACM, Volume 23, Issue 1, January 1980, pp. 17-19.
91 For an input string S of length N, we use hash H = S[N - 1] + N - 105, which
92 for the current set of qualifiers yields a unique H in the range [0 .. 20].
93 The hash can be modified when the keyword set changes as necessary. We also
94 store the length of each keyword and check it prior to the final strcmp().
96 TODO: just use gperf. */
99 isqualifier (const char *s
, size_t len
)
101 static const struct qual
106 {"static", 6}, {"", 0}, {"", 0}, {"", 0},
107 {"volatile", 8}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
108 {"", 0}, {"auto", 4}, {"extern", 6}, {"", 0}, {"", 0},
109 {"", 0}, {"", 0}, {"const", 5}, {"register", 8},
110 {"", 0}, {"restrict", 8}, {"_Restrict", 9}
113 int h
= s
[len
- 1] + (int) len
- 105;
114 const struct qual
*qp
;
116 if (h
< 0 || (size_t) h
>= sizeof (qhash
) / sizeof (qhash
[0]))
121 return ((size_t) len
== qp
->q_len
&&
122 strncmp (qp
->q_name
, s
, qp
->q_len
) == 0);
125 /* Attempt to convert the given C type name into the corresponding CTF type ID.
126 It is not possible to do complete and proper conversion of type names
127 without implementing a more full-fledged parser, which is necessary to
128 handle things like types that are function pointers to functions that
129 have arguments that are function pointers, and fun stuff like that.
130 Instead, this function implements a very simple conversion algorithm that
131 finds the things that we actually care about: structs, unions, enums,
132 integers, floats, typedefs, and pointers to any of these named types. */
135 ctf_lookup_by_name_internal (ctf_dict_t
*fp
, ctf_dict_t
*child
,
138 static const char delimiters
[] = " \t\n\r\v\f*";
140 const ctf_lookup_t
*lp
;
141 const char *p
, *q
, *end
;
143 ctf_id_t ntype
, ptype
;
146 return (ctf_set_errno (fp
, EINVAL
));
148 for (p
= name
, end
= name
+ strlen (name
); *p
!= '\0'; p
= q
)
150 while (isspace ((int) *p
))
151 p
++; /* Skip leading whitespace. */
156 if ((q
= strpbrk (p
+ 1, delimiters
)) == NULL
)
157 q
= end
; /* Compare until end. */
161 /* Find a pointer to type by looking in child->ctf_pptrtab (if child
162 is set) and fp->ctf_ptrtab. If we can't find a pointer to the
163 given type, see if we can compute a pointer to the type resulting
164 from resolving the type down to its base type and use that instead.
165 This helps with cases where the CTF data includes "struct foo *"
166 but not "foo_t *" and the user tries to access "foo_t *" in the
169 There is extra complexity here because uninitialized elements in
170 the pptrtab and ptrtab are set to zero, but zero (as the type ID
171 meaning the unimplemented type) is a valid return type from
172 ctf_lookup_by_name. (Pointers to types are never of type 0, so
173 this is unambiguous, just fiddly to deal with.) */
175 uint32_t idx
= LCTF_TYPE_TO_INDEX (fp
, type
);
179 if (child
&& idx
< child
->ctf_pptrtab_len
)
181 ntype
= child
->ctf_pptrtab
[idx
];
188 if (ntype
== CTF_ERR
)
190 ntype
= fp
->ctf_ptrtab
[idx
];
195 /* Try resolving to its base type and check again. */
196 if (ntype
== CTF_ERR
)
199 ntype
= ctf_type_resolve_unsliced (child
, type
);
201 ntype
= ctf_type_resolve_unsliced (fp
, type
);
203 if (ntype
== CTF_ERR
)
206 idx
= LCTF_TYPE_TO_INDEX (fp
, ntype
);
209 if (child
&& idx
< child
->ctf_pptrtab_len
)
211 ntype
= child
->ctf_pptrtab
[idx
];
218 if (ntype
== CTF_ERR
)
220 ntype
= fp
->ctf_ptrtab
[idx
];
224 if (ntype
== CTF_ERR
)
228 type
= LCTF_INDEX_TO_TYPE (fp
, ntype
, (fp
->ctf_flags
& LCTF_CHILD
)
231 /* We are looking up a type in the parent, but the pointed-to type is
232 in the child. Switch to looking in the child: if we need to go
233 back into the parent, we can recurse again. */
244 if (isqualifier (p
, (size_t) (q
- p
)))
245 continue; /* Skip qualifier keyword. */
247 for (lp
= fp
->ctf_lookups
; lp
->ctl_prefix
!= NULL
; lp
++)
249 /* TODO: This is not MT-safe. */
250 if ((lp
->ctl_prefix
[0] == '\0' ||
251 strncmp (p
, lp
->ctl_prefix
, (size_t) (q
- p
)) == 0) &&
252 (size_t) (q
- p
) >= lp
->ctl_len
)
254 for (p
+= lp
->ctl_len
; isspace ((int) *p
); p
++)
255 continue; /* Skip prefix and next whitespace. */
257 if ((q
= strchr (p
, '*')) == NULL
)
258 q
= end
; /* Compare until end. */
260 while (isspace ((int) q
[-1]))
261 q
--; /* Exclude trailing whitespace. */
263 /* Expand and/or allocate storage for a slice of the name, then
266 if (fp
->ctf_tmp_typeslicelen
>= (size_t) (q
- p
) + 1)
268 memcpy (fp
->ctf_tmp_typeslice
, p
, (size_t) (q
- p
));
269 fp
->ctf_tmp_typeslice
[(size_t) (q
- p
)] = '\0';
273 free (fp
->ctf_tmp_typeslice
);
274 fp
->ctf_tmp_typeslice
= xstrndup (p
, (size_t) (q
- p
));
275 if (fp
->ctf_tmp_typeslice
== NULL
)
277 ctf_set_errno (fp
, ENOMEM
);
282 if ((type
= ctf_lookup_by_rawhash (fp
, lp
->ctl_hash
,
283 fp
->ctf_tmp_typeslice
)) == 0)
290 if (lp
->ctl_prefix
== NULL
)
294 if (*p
!= '\0' || type
== 0)
295 return (ctf_set_errno (fp
, ECTF_SYNTAX
));
300 ctf_set_errno (fp
, ECTF_NOTYPE
);
301 if (fp
->ctf_parent
!= NULL
)
303 /* Need to look up in the parent, from the child's perspective.
304 Make sure the pptrtab is up to date. */
306 if (fp
->ctf_pptrtab_typemax
< fp
->ctf_typemax
)
308 if (refresh_pptrtab (fp
, fp
->ctf_parent
) < 0)
309 return -1; /* errno is set for us. */
312 if ((ptype
= ctf_lookup_by_name_internal (fp
->ctf_parent
, fp
,
315 return (ctf_set_errno (fp
, ctf_errno (fp
->ctf_parent
)));
322 ctf_lookup_by_name (ctf_dict_t
*fp
, const char *name
)
324 return ctf_lookup_by_name_internal (fp
, NULL
, name
);
327 /* Return the pointer to the internal CTF type data corresponding to the
328 given type ID. If the ID is invalid, the function returns NULL.
329 This function is not exported outside of the library. */
332 ctf_lookup_by_id (ctf_dict_t
**fpp
, ctf_id_t type
)
334 ctf_dict_t
*fp
= *fpp
; /* Caller passes in starting CTF dict. */
337 if ((fp
= ctf_get_dict (fp
, type
)) == NULL
)
339 (void) ctf_set_errno (*fpp
, ECTF_NOPARENT
);
343 /* If this dict is writable, check for a dynamic type. */
345 if (fp
->ctf_flags
& LCTF_RDWR
)
349 if ((dtd
= ctf_dynamic_type (fp
, type
)) != NULL
)
352 return &dtd
->dtd_data
;
354 (void) ctf_set_errno (*fpp
, ECTF_BADID
);
358 /* Check for a type in the static portion. */
360 idx
= LCTF_TYPE_TO_INDEX (fp
, type
);
361 if (idx
> 0 && (unsigned long) idx
<= fp
->ctf_typemax
)
363 *fpp
= fp
; /* Function returns ending CTF dict. */
364 return (LCTF_INDEX_TO_TYPEPTR (fp
, idx
));
367 (void) ctf_set_errno (*fpp
, ECTF_BADID
);
371 typedef struct ctf_lookup_idx_key
374 const char *clik_name
;
375 uint32_t *clik_names
;
376 } ctf_lookup_idx_key_t
;
378 /* A bsearch function for variable names. */
381 ctf_lookup_var (const void *key_
, const void *lookup_
)
383 const ctf_lookup_idx_key_t
*key
= key_
;
384 const ctf_varent_t
*lookup
= lookup_
;
386 return (strcmp (key
->clik_name
, ctf_strptr (key
->clik_fp
, lookup
->ctv_name
)));
389 /* Given a variable name, return the type of the variable with that name. */
392 ctf_lookup_variable (ctf_dict_t
*fp
, const char *name
)
395 ctf_lookup_idx_key_t key
= { fp
, name
, NULL
};
397 /* This array is sorted, so we can bsearch for it. */
399 ent
= bsearch (&key
, fp
->ctf_vars
, fp
->ctf_nvars
, sizeof (ctf_varent_t
),
404 if (fp
->ctf_parent
!= NULL
)
405 return ctf_lookup_variable (fp
->ctf_parent
, name
);
407 return (ctf_set_errno (fp
, ECTF_NOTYPEDAT
));
410 return ent
->ctv_type
;
413 typedef struct ctf_symidx_sort_arg_cb
417 } ctf_symidx_sort_arg_cb_t
;
420 sort_symidx_by_name (const void *one_
, const void *two_
, void *arg_
)
422 const uint32_t *one
= one_
;
423 const uint32_t *two
= two_
;
424 ctf_symidx_sort_arg_cb_t
*arg
= arg_
;
426 return (strcmp (ctf_strptr (arg
->fp
, arg
->names
[*one
]),
427 ctf_strptr (arg
->fp
, arg
->names
[*two
])));
430 /* Sort a symbol index section by name. Takes a 1:1 mapping of names to the
431 corresponding symbol table. Returns a lexicographically sorted array of idx
432 indexes (and thus, of indexes into the corresponding func info / data object
436 ctf_symidx_sort (ctf_dict_t
*fp
, uint32_t *idx
, size_t *nidx
,
442 if ((sorted
= malloc (len
)) == NULL
)
444 ctf_set_errno (fp
, ENOMEM
);
448 *nidx
= len
/ sizeof (uint32_t);
449 for (i
= 0; i
< *nidx
; i
++)
452 if (!(fp
->ctf_header
->cth_flags
& CTF_F_IDXSORTED
))
454 ctf_symidx_sort_arg_cb_t arg
= { fp
, idx
};
455 ctf_dprintf ("Index section unsorted: sorting.");
456 ctf_qsort_r (sorted
, *nidx
, sizeof (uint32_t), sort_symidx_by_name
, &arg
);
457 fp
->ctf_header
->cth_flags
|= CTF_F_IDXSORTED
;
463 /* Given a symbol index, return the name of that symbol from the table provided
464 by ctf_link_shuffle_syms, or failing that from the secondary string table, or
467 ctf_lookup_symbol_name (ctf_dict_t
*fp
, unsigned long symidx
)
469 const ctf_sect_t
*sp
= &fp
->ctf_symtab
;
473 if (fp
->ctf_dynsymidx
)
476 if (symidx
> fp
->ctf_dynsymmax
)
479 ctf_link_sym_t
*symp
= fp
->ctf_dynsymidx
[symidx
];
484 return symp
->st_name
;
488 if (sp
->cts_data
== NULL
)
491 if (symidx
>= fp
->ctf_nsyms
)
494 switch (sp
->cts_entsize
)
496 case sizeof (Elf64_Sym
):
498 const Elf64_Sym
*symp
= (Elf64_Sym
*) sp
->cts_data
+ symidx
;
499 ctf_elf64_to_link_sym (fp
, &sym
, symp
, symidx
);
502 case sizeof (Elf32_Sym
):
504 const Elf32_Sym
*symp
= (Elf32_Sym
*) sp
->cts_data
+ symidx
;
505 ctf_elf32_to_link_sym (fp
, &sym
, symp
, symidx
);
509 ctf_set_errno (fp
, ECTF_SYMTAB
);
513 assert (!sym
.st_nameidx_set
);
521 ret
= ctf_lookup_symbol_name (fp
->ctf_parent
, symidx
);
523 ctf_set_errno (fp
, ctf_errno (fp
->ctf_parent
));
528 ctf_set_errno (fp
, err
);
533 /* Given a symbol name, return the index of that symbol, or -1 on error or if
536 ctf_lookup_symbol_idx (ctf_dict_t
*fp
, const char *symname
)
538 const ctf_sect_t
*sp
= &fp
->ctf_symtab
;
542 ctf_dict_t
*cache
= fp
;
548 ctf_link_sym_t
*symp
;
550 if ((symp
= ctf_dynhash_lookup (fp
->ctf_dynsyms
, symname
)) == NULL
)
553 return symp
->st_symidx
;
557 if (sp
->cts_data
== NULL
)
560 /* First, try a hash lookup to see if we have already spotted this symbol
561 during a past iteration: create the hash first if need be. The lifespan
562 of the strings is equal to the lifespan of the cts_data, so we don't
563 need to strdup them. If this dict was opened as part of an archive,
564 and this archive has designed a crossdict_cache to cache results that
565 are the same across all dicts in an archive, use it. */
567 if (fp
->ctf_archive
&& fp
->ctf_archive
->ctfi_crossdict_cache
)
568 cache
= fp
->ctf_archive
->ctfi_crossdict_cache
;
570 if (!cache
->ctf_symhash
)
571 if ((cache
->ctf_symhash
= ctf_dynhash_create (ctf_hash_string
,
573 NULL
, NULL
)) == NULL
)
576 if (ctf_dynhash_lookup_kv (cache
->ctf_symhash
, symname
, NULL
, &known_idx
))
577 return (unsigned long) (uintptr_t) known_idx
;
579 /* Hash lookup unsuccessful: linear search, populating the hashtab for later
582 for (; cache
->ctf_symhash_latest
< sp
->cts_size
/ sp
->cts_entsize
;
583 cache
->ctf_symhash_latest
++)
585 switch (sp
->cts_entsize
)
587 case sizeof (Elf64_Sym
):
589 Elf64_Sym
*symp
= (Elf64_Sym
*) sp
->cts_data
;
590 ctf_elf64_to_link_sym (fp
, &sym
, &symp
[cache
->ctf_symhash_latest
],
591 cache
->ctf_symhash_latest
);
592 if (!ctf_dynhash_lookup_kv (cache
->ctf_symhash
, sym
.st_name
,
594 if (ctf_dynhash_cinsert (cache
->ctf_symhash
, sym
.st_name
,
595 (const void *) (uintptr_t)
596 cache
->ctf_symhash_latest
) < 0)
598 if (strcmp (sym
.st_name
, symname
) == 0)
599 return cache
->ctf_symhash_latest
++;
602 case sizeof (Elf32_Sym
):
604 Elf32_Sym
*symp
= (Elf32_Sym
*) sp
->cts_data
;
605 ctf_elf32_to_link_sym (fp
, &sym
, &symp
[cache
->ctf_symhash_latest
],
606 cache
->ctf_symhash_latest
);
607 if (!ctf_dynhash_lookup_kv (cache
->ctf_symhash
, sym
.st_name
,
609 if (ctf_dynhash_cinsert (cache
->ctf_symhash
, sym
.st_name
,
610 (const void *) (uintptr_t)
611 cache
->ctf_symhash_latest
) < 0)
613 if (strcmp (sym
.st_name
, symname
) == 0)
614 return cache
->ctf_symhash_latest
++;
618 ctf_set_errno (fp
, ECTF_SYMTAB
);
619 return (unsigned long) -1;
623 /* Searched everything, still not found. */
625 return (unsigned long) -1;
629 return ctf_lookup_symbol_idx (fp
->ctf_parent
, symname
);
632 ctf_set_errno (fp
, err
);
633 return (unsigned long) -1;
636 ctf_set_errno (fp
, ENOMEM
);
637 ctf_err_warn (fp
, 0, ENOMEM
, _("cannot allocate memory for symbol "
639 return (unsigned long) -1;
643 /* Iterate over all symbols with types: if FUNC, function symbols, otherwise,
644 data symbols. The name argument is not optional. The return order is
645 arbitrary, though is likely to be in symbol index or name order. You can
646 change the value of 'functions' in the middle of iteration over non-dynamic
647 dicts, but doing so on dynamic dicts will fail. (This is probably not very
648 useful, but there is no reason to prohibit it.) */
651 ctf_symbol_next (ctf_dict_t
*fp
, ctf_next_t
**it
, const char **name
,
660 if ((i
= ctf_next_create ()) == NULL
)
661 return ctf_set_errno (fp
, ENOMEM
);
664 i
->ctn_iter_fun
= (void (*) (void)) ctf_symbol_next
;
669 if ((void (*) (void)) ctf_symbol_next
!= i
->ctn_iter_fun
)
670 return (ctf_set_errno (fp
, ECTF_NEXT_WRONGFUN
));
672 if (fp
!= i
->cu
.ctn_fp
)
673 return (ctf_set_errno (fp
, ECTF_NEXT_WRONGFP
));
675 /* We intentionally use raw access, not ctf_lookup_by_symbol, to avoid
676 incurring additional sorting cost for unsorted symtypetabs coming from the
677 compiler, to allow ctf_symbol_next to work in the absence of a symtab, and
678 finally because it's easier to work out what the name of each symbol is if
681 if (fp
->ctf_flags
& LCTF_RDWR
)
683 ctf_dynhash_t
*dynh
= functions
? fp
->ctf_funchash
: fp
->ctf_objthash
;
684 void *dyn_name
= NULL
, *dyn_value
= NULL
;
688 ctf_next_destroy (i
);
689 return (ctf_set_errno (fp
, ECTF_NEXT_END
));
692 err
= ctf_dynhash_next (dynh
, &i
->ctn_next
, &dyn_name
, &dyn_value
);
693 /* This covers errors and also end-of-iteration. */
696 ctf_next_destroy (i
);
698 return ctf_set_errno (fp
, err
);
702 sym
= (ctf_id_t
) (uintptr_t) dyn_value
;
704 else if ((!functions
&& fp
->ctf_objtidx_names
) ||
705 (functions
&& fp
->ctf_funcidx_names
))
707 ctf_header_t
*hp
= fp
->ctf_header
;
708 uint32_t *idx
= functions
? fp
->ctf_funcidx_names
: fp
->ctf_objtidx_names
;
714 len
= (hp
->cth_varoff
- hp
->cth_funcidxoff
) / sizeof (uint32_t);
715 tab
= (uint32_t *) (fp
->ctf_buf
+ hp
->cth_funcoff
);
719 len
= (hp
->cth_funcidxoff
- hp
->cth_objtidxoff
) / sizeof (uint32_t);
720 tab
= (uint32_t *) (fp
->ctf_buf
+ hp
->cth_objtoff
);
728 *name
= ctf_strptr (fp
, idx
[i
->ctn_n
]);
729 sym
= tab
[i
->ctn_n
++];
731 while (sym
== -1u || sym
== 0);
735 /* Skip over pads in ctf_xslate, padding for typeless symbols in the
736 symtypetab itself, and symbols in the wrong table. */
737 for (; i
->ctn_n
< fp
->ctf_nsyms
; i
->ctn_n
++)
739 ctf_header_t
*hp
= fp
->ctf_header
;
741 if (fp
->ctf_sxlate
[i
->ctn_n
] == -1u)
744 sym
= *(uint32_t *) ((uintptr_t) fp
->ctf_buf
+ fp
->ctf_sxlate
[i
->ctn_n
]);
751 if (fp
->ctf_sxlate
[i
->ctn_n
] >= hp
->cth_funcoff
752 && fp
->ctf_sxlate
[i
->ctn_n
] < hp
->cth_objtidxoff
)
757 if (fp
->ctf_sxlate
[i
->ctn_n
] >= hp
->cth_objtoff
758 && fp
->ctf_sxlate
[i
->ctn_n
] < hp
->cth_funcoff
)
763 if (i
->ctn_n
>= fp
->ctf_nsyms
)
766 *name
= ctf_lookup_symbol_name (fp
, i
->ctn_n
++);
772 ctf_next_destroy (i
);
774 return (ctf_set_errno (fp
, ECTF_NEXT_END
));
777 /* A bsearch function for function and object index names. */
780 ctf_lookup_idx_name (const void *key_
, const void *idx_
)
782 const ctf_lookup_idx_key_t
*key
= key_
;
783 const uint32_t *idx
= idx_
;
785 return (strcmp (key
->clik_name
, ctf_strptr (key
->clik_fp
, key
->clik_names
[*idx
])));
788 /* Given a symbol name or (failing that) number, look up that symbol in the
789 function or object index table (which must exist). Return 0 if not found
793 ctf_try_lookup_indexed (ctf_dict_t
*fp
, unsigned long symidx
,
794 const char *symname
, int is_function
)
796 struct ctf_header
*hp
= fp
->ctf_header
;
797 uint32_t *symtypetab
;
803 symname
= ctf_lookup_symbol_name (fp
, symidx
);
805 ctf_dprintf ("Looking up type of object with symtab idx %lx or name %s in "
806 "indexed symtypetab\n", symidx
, symname
);
808 if (symname
[0] == '\0')
809 return -1; /* errno is set for us. */
813 if (!fp
->ctf_funcidx_sxlate
)
815 if ((fp
->ctf_funcidx_sxlate
816 = ctf_symidx_sort (fp
, (uint32_t *)
817 (fp
->ctf_buf
+ hp
->cth_funcidxoff
),
819 hp
->cth_varoff
- hp
->cth_funcidxoff
))
822 ctf_err_warn (fp
, 0, 0, _("cannot sort function symidx"));
823 return -1; /* errno is set for us. */
826 symtypetab
= (uint32_t *) (fp
->ctf_buf
+ hp
->cth_funcoff
);
827 sxlate
= fp
->ctf_funcidx_sxlate
;
828 names
= fp
->ctf_funcidx_names
;
829 nidx
= fp
->ctf_nfuncidx
;
833 if (!fp
->ctf_objtidx_sxlate
)
835 if ((fp
->ctf_objtidx_sxlate
836 = ctf_symidx_sort (fp
, (uint32_t *)
837 (fp
->ctf_buf
+ hp
->cth_objtidxoff
),
839 hp
->cth_funcidxoff
- hp
->cth_objtidxoff
))
842 ctf_err_warn (fp
, 0, 0, _("cannot sort object symidx"));
843 return -1; /* errno is set for us. */
847 symtypetab
= (uint32_t *) (fp
->ctf_buf
+ hp
->cth_objtoff
);
848 sxlate
= fp
->ctf_objtidx_sxlate
;
849 names
= fp
->ctf_objtidx_names
;
850 nidx
= fp
->ctf_nobjtidx
;
853 ctf_lookup_idx_key_t key
= { fp
, symname
, names
};
856 idx
= bsearch (&key
, sxlate
, nidx
, sizeof (uint32_t), ctf_lookup_idx_name
);
860 ctf_dprintf ("%s not found in idx\n", symname
);
864 /* Should be impossible, but be paranoid. */
865 if ((idx
- sxlate
) > (ptrdiff_t) nidx
)
866 return (ctf_set_errno (fp
, ECTF_CORRUPT
));
868 ctf_dprintf ("Symbol %lx (%s) is of type %x\n", symidx
, symname
,
870 return symtypetab
[*idx
];
873 /* Given a symbol name or (if NULL) symbol index, return the type of the
874 function or data object described by the corresponding entry in the symbol
875 table. We can only return symbols in read-only dicts and in dicts for which
876 ctf_link_shuffle_syms has been called to assign symbol indexes to symbol
880 ctf_lookup_by_sym_or_name (ctf_dict_t
*fp
, unsigned long symidx
,
883 const ctf_sect_t
*sp
= &fp
->ctf_symtab
;
887 /* Shuffled dynsymidx present? Use that. */
888 if (fp
->ctf_dynsymidx
)
890 const ctf_link_sym_t
*sym
;
893 ctf_dprintf ("Looking up type of object with symname %s in "
894 "writable dict symtypetab\n", symname
);
896 ctf_dprintf ("Looking up type of object with symtab idx %lx in "
897 "writable dict symtypetab\n", symidx
);
899 /* The dict must be dynamic. */
900 if (!ctf_assert (fp
, fp
->ctf_flags
& LCTF_RDWR
))
903 /* No name? Need to look it up. */
907 if (symidx
> fp
->ctf_dynsymmax
)
910 sym
= fp
->ctf_dynsymidx
[symidx
];
911 err
= ECTF_NOTYPEDAT
;
912 if (!sym
|| (sym
->st_shndx
!= STT_OBJECT
&& sym
->st_shndx
!= STT_FUNC
))
915 if (!ctf_assert (fp
, !sym
->st_nameidx_set
))
917 symname
= sym
->st_name
;
920 if (fp
->ctf_objthash
== NULL
921 || ((type
= (ctf_id_t
) (uintptr_t)
922 ctf_dynhash_lookup (fp
->ctf_objthash
, symname
)) == 0))
924 if (fp
->ctf_funchash
== NULL
925 || ((type
= (ctf_id_t
) (uintptr_t)
926 ctf_dynhash_lookup (fp
->ctf_funchash
, symname
)) == 0))
933 /* Lookup by name in a dynamic dict: just do it directly. */
934 if (symname
&& fp
->ctf_flags
& LCTF_RDWR
)
936 if (fp
->ctf_objthash
== NULL
937 || ((type
= (ctf_id_t
) (uintptr_t)
938 ctf_dynhash_lookup (fp
->ctf_objthash
, symname
)) == 0))
940 if (fp
->ctf_funchash
== NULL
941 || ((type
= (ctf_id_t
) (uintptr_t)
942 ctf_dynhash_lookup (fp
->ctf_funchash
, symname
)) == 0))
949 if (sp
->cts_data
== NULL
)
952 /* This covers both out-of-range lookups and a dynamic dict which hasn't been
955 if (symname
== NULL
&& symidx
>= fp
->ctf_nsyms
)
958 if (fp
->ctf_objtidx_names
)
960 if ((type
= ctf_try_lookup_indexed (fp
, symidx
, symname
, 0)) == CTF_ERR
)
961 return CTF_ERR
; /* errno is set for us. */
963 if (type
== 0 && fp
->ctf_funcidx_names
)
965 if ((type
= ctf_try_lookup_indexed (fp
, symidx
, symname
, 1)) == CTF_ERR
)
966 return CTF_ERR
; /* errno is set for us. */
971 err
= ECTF_NOTYPEDAT
;
972 if (fp
->ctf_objtidx_names
&& fp
->ctf_funcidx_names
)
975 /* Table must be nonindexed. */
977 ctf_dprintf ("Looking up object type %lx in 1:1 dict symtypetab\n", symidx
);
980 if ((symidx
= ctf_lookup_symbol_idx (fp
, symname
)) == (unsigned long) -1)
983 if (fp
->ctf_sxlate
[symidx
] == -1u)
986 type
= *(uint32_t *) ((uintptr_t) fp
->ctf_buf
+ fp
->ctf_sxlate
[symidx
]);
995 ctf_id_t ret
= ctf_lookup_by_sym_or_name (fp
->ctf_parent
, symidx
,
998 ctf_set_errno (fp
, ctf_errno (fp
->ctf_parent
));
1002 return (ctf_set_errno (fp
, err
));
1005 /* Given a symbol table index, return the type of the function or data object
1006 described by the corresponding entry in the symbol table. */
1008 ctf_lookup_by_symbol (ctf_dict_t
*fp
, unsigned long symidx
)
1010 return ctf_lookup_by_sym_or_name (fp
, symidx
, NULL
);
1013 /* Given a symbol name, return the type of the function or data object described
1014 by the corresponding entry in the symbol table. */
1016 ctf_lookup_by_symbol_name (ctf_dict_t
*fp
, const char *symname
)
1018 return ctf_lookup_by_sym_or_name (fp
, 0, symname
);
1021 /* Given a symbol table index, return the info for the function described
1022 by the corresponding entry in the symbol table, which may be a function
1023 symbol or may be a data symbol that happens to be a function pointer. */
1026 ctf_func_info (ctf_dict_t
*fp
, unsigned long symidx
, ctf_funcinfo_t
*fip
)
1030 if ((type
= ctf_lookup_by_symbol (fp
, symidx
)) == CTF_ERR
)
1031 return -1; /* errno is set for us. */
1033 if (ctf_type_kind (fp
, type
) != CTF_K_FUNCTION
)
1034 return (ctf_set_errno (fp
, ECTF_NOTFUNC
));
1036 return ctf_func_type_info (fp
, type
, fip
);
1039 /* Given a symbol table index, return the arguments for the function described
1040 by the corresponding entry in the symbol table. */
1043 ctf_func_args (ctf_dict_t
*fp
, unsigned long symidx
, uint32_t argc
,
1048 if ((type
= ctf_lookup_by_symbol (fp
, symidx
)) == CTF_ERR
)
1049 return -1; /* errno is set for us. */
1051 if (ctf_type_kind (fp
, type
) != CTF_K_FUNCTION
)
1052 return (ctf_set_errno (fp
, ECTF_NOTFUNC
));
1054 return ctf_func_type_args (fp
, type
, argc
, argv
);