aboutsummaryrefslogtreecommitdiff
path: root/libctf/ctf-lookup.c
diff options
context:
space:
mode:
Diffstat (limited to 'libctf/ctf-lookup.c')
-rw-r--r--libctf/ctf-lookup.c572
1 files changed, 440 insertions, 132 deletions
diff --git a/libctf/ctf-lookup.c b/libctf/ctf-lookup.c
index 5682bf0..a862b40 100644
--- a/libctf/ctf-lookup.c
+++ b/libctf/ctf-lookup.c
@@ -20,6 +20,7 @@
#include <ctf-impl.h>
#include <elf.h>
#include <string.h>
+#include <assert.h>
/* Compare the given input string and length against a table of known C storage
qualifier keywords. We just ignore these in ctf_lookup_by_name, below. To
@@ -192,21 +193,66 @@ err:
return CTF_ERR;
}
-typedef struct ctf_lookup_var_key
+/* Return the pointer to the internal CTF type data corresponding to the
+ given type ID. If the ID is invalid, the function returns NULL.
+ This function is not exported outside of the library. */
+
+const ctf_type_t *
+ctf_lookup_by_id (ctf_dict_t **fpp, ctf_id_t type)
{
- ctf_dict_t *clvk_fp;
- const char *clvk_name;
-} ctf_lookup_var_key_t;
+ ctf_dict_t *fp = *fpp; /* Caller passes in starting CTF dict. */
+ ctf_id_t idx;
+
+ if ((fp = ctf_get_dict (fp, type)) == NULL)
+ {
+ (void) ctf_set_errno (*fpp, ECTF_NOPARENT);
+ return NULL;
+ }
+
+ /* If this dict is writable, check for a dynamic type. */
+
+ if (fp->ctf_flags & LCTF_RDWR)
+ {
+ ctf_dtdef_t *dtd;
+
+ if ((dtd = ctf_dynamic_type (fp, type)) != NULL)
+ {
+ *fpp = fp;
+ return &dtd->dtd_data;
+ }
+ (void) ctf_set_errno (*fpp, ECTF_BADID);
+ return NULL;
+ }
+
+ /* Check for a type in the static portion. */
+
+ idx = LCTF_TYPE_TO_INDEX (fp, type);
+ if (idx > 0 && (unsigned long) idx <= fp->ctf_typemax)
+ {
+ *fpp = fp; /* Function returns ending CTF dict. */
+ return (LCTF_INDEX_TO_TYPEPTR (fp, idx));
+ }
+
+ (void) ctf_set_errno (*fpp, ECTF_BADID);
+ return NULL;
+}
+
+typedef struct ctf_lookup_idx_key
+{
+ ctf_dict_t *clik_fp;
+ const char *clik_name;
+ uint32_t *clik_names;
+} ctf_lookup_idx_key_t;
/* A bsearch function for variable names. */
static int
-ctf_lookup_var (const void *key_, const void *memb_)
+ctf_lookup_var (const void *key_, const void *lookup_)
{
- const ctf_lookup_var_key_t *key = key_;
- const ctf_varent_t *memb = memb_;
+ const ctf_lookup_idx_key_t *key = key_;
+ const ctf_varent_t *lookup = lookup_;
- return (strcmp (key->clvk_name, ctf_strptr (key->clvk_fp, memb->ctv_name)));
+ return (strcmp (key->clik_name, ctf_strptr (key->clik_fp, lookup->ctv_name)));
}
/* Given a variable name, return the type of the variable with that name. */
@@ -215,7 +261,7 @@ ctf_id_t
ctf_lookup_variable (ctf_dict_t *fp, const char *name)
{
ctf_varent_t *ent;
- ctf_lookup_var_key_t key = { fp, name };
+ ctf_lookup_idx_key_t key = { fp, name, NULL };
/* This array is sorted, so we can bsearch for it. */
@@ -233,189 +279,457 @@ ctf_lookup_variable (ctf_dict_t *fp, const char *name)
return ent->ctv_type;
}
-/* Given a symbol table index, return the name of that symbol from the secondary
- string table, or the null string (never NULL). */
+typedef struct ctf_symidx_sort_arg_cb
+{
+ ctf_dict_t *fp;
+ uint32_t *names;
+} ctf_symidx_sort_arg_cb_t;
+
+static int
+sort_symidx_by_name (const void *one_, const void *two_, void *arg_)
+{
+ const uint32_t *one = one_;
+ const uint32_t *two = two_;
+ ctf_symidx_sort_arg_cb_t *arg = arg_;
+
+ return (strcmp (ctf_strptr (arg->fp, arg->names[*one]),
+ ctf_strptr (arg->fp, arg->names[*two])));
+}
+
+/* Sort a symbol index section by name. Takes a 1:1 mapping of names to the
+ corresponding symbol table. Returns a lexicographically sorted array of idx
+ indexes (and thus, of indexes into the corresponding func info / data object
+ section). */
+
+static uint32_t *
+ctf_symidx_sort (ctf_dict_t *fp, uint32_t *idx, size_t *nidx,
+ size_t len)
+{
+ uint32_t *sorted;
+ size_t i;
+
+ if ((sorted = malloc (len)) == NULL)
+ {
+ ctf_set_errno (fp, ENOMEM);
+ return NULL;
+ }
+
+ *nidx = len / sizeof (uint32_t);
+ for (i = 0; i < *nidx; i++)
+ sorted[i] = i;
+
+ if (!(fp->ctf_header->cth_flags & CTF_F_IDXSORTED))
+ {
+ ctf_symidx_sort_arg_cb_t arg = { fp, idx };
+ ctf_dprintf ("Index section unsorted: sorting.");
+ ctf_qsort_r (sorted, *nidx, sizeof (uint32_t), sort_symidx_by_name, &arg);
+ fp->ctf_header->cth_flags |= CTF_F_IDXSORTED;
+ }
+
+ return sorted;
+}
+
+/* Given a symbol index, return the name of that symbol from the table provided
+ by ctf_link_shuffle_syms, or failing that from the secondary string table, or
+ the null string. */
const char *
ctf_lookup_symbol_name (ctf_dict_t *fp, unsigned long symidx)
{
const ctf_sect_t *sp = &fp->ctf_symtab;
- Elf64_Sym sym, *gsp;
+ ctf_link_sym_t sym;
+ int err;
- if (sp->cts_data == NULL)
+ if (fp->ctf_dynsymidx)
{
- ctf_set_errno (fp, ECTF_NOSYMTAB);
- return _CTF_NULLSTR;
+ err = EINVAL;
+ if (symidx > fp->ctf_dynsymmax)
+ goto try_parent;
+
+ ctf_link_sym_t *symp = fp->ctf_dynsymidx[symidx];
+
+ if (!symp)
+ goto try_parent;
+
+ return symp->st_name;
}
+ err = ECTF_NOSYMTAB;
+ if (sp->cts_data == NULL)
+ goto try_parent;
+
if (symidx >= fp->ctf_nsyms)
+ goto try_parent;
+
+ switch (sp->cts_entsize)
{
- ctf_set_errno (fp, EINVAL);
+ case sizeof (Elf64_Sym):
+ {
+ const Elf64_Sym *symp = (Elf64_Sym *) sp->cts_data + symidx;
+ ctf_elf64_to_link_sym (fp, &sym, symp, symidx);
+ }
+ break;
+ case sizeof (Elf32_Sym):
+ {
+ const Elf32_Sym *symp = (Elf32_Sym *) sp->cts_data + symidx;
+ ctf_elf32_to_link_sym (fp, &sym, symp, symidx);
+ }
+ break;
+ default:
+ ctf_set_errno (fp, ECTF_SYMTAB);
return _CTF_NULLSTR;
}
- if (sp->cts_entsize == sizeof (Elf32_Sym))
- {
- const Elf32_Sym *symp = (Elf32_Sym *) sp->cts_data + symidx;
- gsp = ctf_sym_to_elf64 (symp, &sym);
- }
- else
- gsp = (Elf64_Sym *) sp->cts_data + symidx;
+ assert (!sym.st_nameidx_set);
- if (gsp->st_name < fp->ctf_str[CTF_STRTAB_1].cts_len)
- return (const char *) fp->ctf_str[CTF_STRTAB_1].cts_strs + gsp->st_name;
+ return sym.st_name;
- return _CTF_NULLSTR;
+ try_parent:
+ if (fp->ctf_parent)
+ return ctf_lookup_symbol_name (fp->ctf_parent, symidx);
+ else
+ {
+ ctf_set_errno (fp, err);
+ return _CTF_NULLSTR;
+ }
}
-/* Given a symbol table index, return the type of the data object described
- by the corresponding entry in the symbol table. */
+/* Iterate over all symbols with types: if FUNC, function symbols, otherwise,
+ data symbols. The name argument is not optional. The return order is
+ arbitrary, though is likely to be in symbol index or name order. You can
+ change the value of 'functions' in the middle of iteration over non-dynamic
+ dicts, but doing so on dynamic dicts will fail. (This is probably not very
+ useful, but there is no reason to prohibit it.) */
ctf_id_t
-ctf_lookup_by_symbol (ctf_dict_t *fp, unsigned long symidx)
+ctf_symbol_next (ctf_dict_t *fp, ctf_next_t **it, const char **name,
+ int functions)
{
- const ctf_sect_t *sp = &fp->ctf_symtab;
- ctf_id_t type;
+ ctf_id_t sym;
+ ctf_next_t *i = *it;
+ int err;
- if (sp->cts_data == NULL)
- return (ctf_set_errno (fp, ECTF_NOSYMTAB));
+ if (!i)
+ {
+ if ((i = ctf_next_create ()) == NULL)
+ return ctf_set_errno (fp, ENOMEM);
- if (symidx >= fp->ctf_nsyms)
- return (ctf_set_errno (fp, EINVAL));
+ i->cu.ctn_fp = fp;
+ i->ctn_iter_fun = (void (*) (void)) ctf_symbol_next;
+ i->ctn_n = 0;
+ *it = i;
+ }
+
+ if ((void (*) (void)) ctf_symbol_next != i->ctn_iter_fun)
+ return (ctf_set_errno (fp, ECTF_NEXT_WRONGFUN));
- if (sp->cts_entsize == sizeof (Elf32_Sym))
+ if (fp != i->cu.ctn_fp)
+ return (ctf_set_errno (fp, ECTF_NEXT_WRONGFP));
+
+ /* We intentionally use raw access, not ctf_lookup_by_symbol, to avoid
+ incurring additional sorting cost for unsorted symtypetabs coming from the
+ compiler, to allow ctf_symbol_next to work in the absence of a symtab, and
+ finally because it's easier to work out what the name of each symbol is if
+ we do that. */
+
+ if (fp->ctf_flags & LCTF_RDWR)
{
- const Elf32_Sym *symp = (Elf32_Sym *) sp->cts_data + symidx;
- if (ELF32_ST_TYPE (symp->st_info) != STT_OBJECT)
- return (ctf_set_errno (fp, ECTF_NOTDATA));
+ ctf_dynhash_t *dynh = functions ? fp->ctf_funchash : fp->ctf_objthash;
+ void *dyn_name = NULL, *dyn_value = NULL;
+
+ if (!dynh)
+ {
+ ctf_next_destroy (i);
+ return (ctf_set_errno (fp, ECTF_NEXT_END));
+ }
+
+ err = ctf_dynhash_next (dynh, &i->u.ctn_next, &dyn_name, &dyn_value);
+ /* This covers errors and also end-of-iteration. */
+ if (err != 0)
+ {
+ ctf_next_destroy (i);
+ *it = NULL;
+ return ctf_set_errno (fp, err);
+ }
+
+ *name = dyn_name;
+ sym = (ctf_id_t) (uintptr_t) dyn_value;
}
- else
+ else if ((!functions && fp->ctf_objtidx_names) ||
+ (functions && fp->ctf_funcidx_names))
{
- const Elf64_Sym *symp = (Elf64_Sym *) sp->cts_data + symidx;
- if (ELF64_ST_TYPE (symp->st_info) != STT_OBJECT)
- return (ctf_set_errno (fp, ECTF_NOTDATA));
+ ctf_header_t *hp = fp->ctf_header;
+ uint32_t *idx = functions ? fp->ctf_funcidx_names : fp->ctf_objtidx_names;
+ uint32_t *tab;
+ size_t len;
+
+ if (functions)
+ {
+ len = (hp->cth_varoff - hp->cth_funcidxoff) / sizeof (uint32_t);
+ tab = (uint32_t *) (fp->ctf_buf + hp->cth_funcoff);
+ }
+ else
+ {
+ len = (hp->cth_funcidxoff - hp->cth_objtidxoff) / sizeof (uint32_t);
+ tab = (uint32_t *) (fp->ctf_buf + hp->cth_objtoff);
+ }
+
+ do
+ {
+ if (i->ctn_n >= len)
+ goto end;
+
+ *name = ctf_strptr (fp, idx[i->ctn_n]);
+ sym = tab[i->ctn_n++];
+ } while (sym == -1u || sym == 0);
}
+ else
+ {
+ /* Skip over pads in ctf_xslate, padding for typeless symbols in the
+ symtypetab itself, and symbols in the wrong table. */
+ for (; i->ctn_n < fp->ctf_nsyms; i->ctn_n++)
+ {
+ ctf_header_t *hp = fp->ctf_header;
- if (fp->ctf_sxlate[symidx] == -1u)
- return (ctf_set_errno (fp, ECTF_NOTYPEDAT));
+ if (fp->ctf_sxlate[i->ctn_n] == -1u)
+ continue;
- type = *(uint32_t *) ((uintptr_t) fp->ctf_buf + fp->ctf_sxlate[symidx]);
- if (type == 0)
- return (ctf_set_errno (fp, ECTF_NOTYPEDAT));
+ sym = *(uint32_t *) ((uintptr_t) fp->ctf_buf + fp->ctf_sxlate[i->ctn_n]);
- return type;
+ if (sym == 0)
+ continue;
+
+ if (functions)
+ {
+ if (fp->ctf_sxlate[i->ctn_n] >= hp->cth_funcoff
+ && fp->ctf_sxlate[i->ctn_n] < hp->cth_objtidxoff)
+ break;
+ }
+ else
+ {
+ if (fp->ctf_sxlate[i->ctn_n] >= hp->cth_objtoff
+ && fp->ctf_sxlate[i->ctn_n] < hp->cth_funcoff)
+ break;
+ }
+ }
+
+ if (i->ctn_n >= fp->ctf_nsyms)
+ goto end;
+
+ *name = ctf_lookup_symbol_name (fp, i->ctn_n++);
+ }
+
+ return sym;
+
+ end:
+ ctf_next_destroy (i);
+ *it = NULL;
+ return (ctf_set_errno (fp, ECTF_NEXT_END));
}
-/* Return the native dict of a given type: if called on a child and the
- type is in the parent, return the parent. Needed if you plan to access
- the type directly, without using the API. */
-ctf_dict_t *
-ctf_get_dict (ctf_dict_t *fp, ctf_id_t type)
+/* A bsearch function for function and object index names. */
+
+static int
+ctf_lookup_idx_name (const void *key_, const void *idx_)
{
- if ((fp->ctf_flags & LCTF_CHILD) && LCTF_TYPE_ISPARENT (fp, type))
- return fp->ctf_parent;
+ const ctf_lookup_idx_key_t *key = key_;
+ const uint32_t *idx = idx_;
- return fp;
+ return (strcmp (key->clik_name, ctf_strptr (key->clik_fp, key->clik_names[*idx])));
}
-/* Return the pointer to the internal CTF type data corresponding to the
- given type ID. If the ID is invalid, the function returns NULL.
- This function is not exported outside of the library. */
+/* Given a symbol number, look up that symbol in the function or object
+ index table (which must exist). Return 0 if not found there (or pad). */
-const ctf_type_t *
-ctf_lookup_by_id (ctf_dict_t **fpp, ctf_id_t type)
+static ctf_id_t
+ctf_try_lookup_indexed (ctf_dict_t *fp, unsigned long symidx, int is_function)
{
- ctf_dict_t *fp = *fpp; /* Caller passes in starting CTF dict. */
- ctf_id_t idx;
+ const char *symname = ctf_lookup_symbol_name (fp, symidx);
+ struct ctf_header *hp = fp->ctf_header;
+ uint32_t *symtypetab;
+ uint32_t *names;
+ uint32_t *sxlate;
+ size_t nidx;
- if ((fp = ctf_get_dict (fp, type)) == NULL)
- {
- (void) ctf_set_errno (*fpp, ECTF_NOPARENT);
- return NULL;
- }
+ ctf_dprintf ("Looking up type of object with symtab idx %lx (%s) in "
+ "indexed symtypetab\n", symidx, symname);
- /* If this dict is writable, check for a dynamic type. */
+ if (symname[0] == '\0')
+ return -1; /* errno is set for us. */
- if (fp->ctf_flags & LCTF_RDWR)
+ if (is_function)
{
- ctf_dtdef_t *dtd;
-
- if ((dtd = ctf_dynamic_type (fp, type)) != NULL)
+ if (!fp->ctf_funcidx_sxlate)
{
- *fpp = fp;
- return &dtd->dtd_data;
+ if ((fp->ctf_funcidx_sxlate
+ = ctf_symidx_sort (fp, (uint32_t *)
+ (fp->ctf_buf + hp->cth_funcidxoff),
+ &fp->ctf_nfuncidx,
+ hp->cth_varoff - hp->cth_funcidxoff))
+ == NULL)
+ {
+ ctf_err_warn (fp, 0, 0, _("cannot sort function symidx"));
+ return -1; /* errno is set for us. */
+ }
}
- (void) ctf_set_errno (*fpp, ECTF_BADID);
- return NULL;
+ symtypetab = (uint32_t *) (fp->ctf_buf + hp->cth_funcoff);
+ sxlate = fp->ctf_funcidx_sxlate;
+ names = fp->ctf_funcidx_names;
+ nidx = fp->ctf_nfuncidx;
}
+ else
+ {
+ if (!fp->ctf_objtidx_sxlate)
+ {
+ if ((fp->ctf_objtidx_sxlate
+ = ctf_symidx_sort (fp, (uint32_t *)
+ (fp->ctf_buf + hp->cth_objtidxoff),
+ &fp->ctf_nobjtidx,
+ hp->cth_funcidxoff - hp->cth_objtidxoff))
+ == NULL)
+ {
+ ctf_err_warn (fp, 0, 0, _("cannot sort object symidx"));
+ return -1; /* errno is set for us. */
+ }
+ }
- /* Check for a type in the static portion. */
+ symtypetab = (uint32_t *) (fp->ctf_buf + hp->cth_objtoff);
+ sxlate = fp->ctf_objtidx_sxlate;
+ names = fp->ctf_objtidx_names;
+ nidx = fp->ctf_nobjtidx;
+ }
- idx = LCTF_TYPE_TO_INDEX (fp, type);
- if (idx > 0 && (unsigned long) idx <= fp->ctf_typemax)
+ ctf_lookup_idx_key_t key = { fp, symname, names };
+ uint32_t *idx;
+
+ idx = bsearch (&key, sxlate, nidx, sizeof (uint32_t), ctf_lookup_idx_name);
+
+ if (!idx)
{
- *fpp = fp; /* Function returns ending CTF dict. */
- return (LCTF_INDEX_TO_TYPEPTR (fp, idx));
+ ctf_dprintf ("%s not found in idx\n", symname);
+ return 0;
}
- (void) ctf_set_errno (*fpp, ECTF_BADID);
- return NULL;
+ /* Should be impossible, but be paranoid. */
+ if ((idx - sxlate) > (ptrdiff_t) nidx)
+ return (ctf_set_errno (fp, ECTF_CORRUPT));
+
+ ctf_dprintf ("Symbol %lx (%s) is of type %x\n", symidx, symname,
+ symtypetab[*idx]);
+ return symtypetab[*idx];
}
-/* Given a symbol table index, return the info for the function described
- by the corresponding entry in the symbol table. */
+/* Given a symbol table index, return the type of the function or data object
+ described by the corresponding entry in the symbol table. We can only return
+ symbols in read-only dicts and in dicts for which ctf_link_shuffle_syms has
+ been called to assign symbol indexes to symbol names. */
-int
-ctf_func_info (ctf_dict_t *fp, unsigned long symidx, ctf_funcinfo_t *fip)
+ctf_id_t
+ctf_lookup_by_symbol (ctf_dict_t *fp, unsigned long symidx)
{
const ctf_sect_t *sp = &fp->ctf_symtab;
- const uint32_t *dp;
- uint32_t info, kind, n;
+ ctf_id_t type = 0;
+ int err = 0;
+
+ /* Shuffled dynsymidx present? Use that. */
+ if (fp->ctf_dynsymidx)
+ {
+ const ctf_link_sym_t *sym;
+
+ ctf_dprintf ("Looking up type of object with symtab idx %lx in "
+ "writable dict symtypetab\n", symidx);
+
+ /* The dict must be dynamic. */
+ if (!ctf_assert (fp, fp->ctf_flags & LCTF_RDWR))
+ return CTF_ERR;
+
+ err = EINVAL;
+ if (symidx > fp->ctf_dynsymmax)
+ goto try_parent;
+
+ sym = fp->ctf_dynsymidx[symidx];
+ err = ECTF_NOTYPEDAT;
+ if (!sym || (sym->st_shndx != STT_OBJECT && sym->st_shndx != STT_FUNC))
+ goto try_parent;
+
+ if (!ctf_assert (fp, !sym->st_nameidx_set))
+ return CTF_ERR;
+
+ if (fp->ctf_objthash == NULL
+ || ((type = (ctf_id_t) (uintptr_t)
+ ctf_dynhash_lookup (fp->ctf_objthash, sym->st_name)) == 0))
+ {
+ if (fp->ctf_funchash == NULL
+ || ((type = (ctf_id_t) (uintptr_t)
+ ctf_dynhash_lookup (fp->ctf_funchash, sym->st_name)) == 0))
+ goto try_parent;
+ }
+
+ return type;
+ }
+ err = ECTF_NOSYMTAB;
if (sp->cts_data == NULL)
- return (ctf_set_errno (fp, ECTF_NOSYMTAB));
+ goto try_parent;
+ /* This covers both out-of-range lookups and a dynamic dict which hasn't been
+ shuffled yet. */
+ err = EINVAL;
if (symidx >= fp->ctf_nsyms)
- return (ctf_set_errno (fp, EINVAL));
+ goto try_parent;
- if (sp->cts_entsize == sizeof (Elf32_Sym))
+ if (fp->ctf_objtidx_names)
{
- const Elf32_Sym *symp = (Elf32_Sym *) sp->cts_data + symidx;
- if (ELF32_ST_TYPE (symp->st_info) != STT_FUNC)
- return (ctf_set_errno (fp, ECTF_NOTFUNC));
+ if ((type = ctf_try_lookup_indexed (fp, symidx, 0)) == CTF_ERR)
+ return CTF_ERR; /* errno is set for us. */
}
- else
+ if (type == 0 && fp->ctf_funcidx_names)
{
- const Elf64_Sym *symp = (Elf64_Sym *) sp->cts_data + symidx;
- if (ELF64_ST_TYPE (symp->st_info) != STT_FUNC)
- return (ctf_set_errno (fp, ECTF_NOTFUNC));
+ if ((type = ctf_try_lookup_indexed (fp, symidx, 1)) == CTF_ERR)
+ return CTF_ERR; /* errno is set for us. */
}
+ if (type != 0)
+ return type;
+
+ err = ECTF_NOTYPEDAT;
+ if (fp->ctf_objtidx_names && fp->ctf_funcidx_names)
+ goto try_parent;
+
+ /* Table must be nonindexed. */
+
+ ctf_dprintf ("Looking up object type %lx in 1:1 dict symtypetab\n", symidx);
if (fp->ctf_sxlate[symidx] == -1u)
- return (ctf_set_errno (fp, ECTF_NOFUNCDAT));
+ goto try_parent;
+
+ type = *(uint32_t *) ((uintptr_t) fp->ctf_buf + fp->ctf_sxlate[symidx]);
- dp = (uint32_t *) ((uintptr_t) fp->ctf_buf + fp->ctf_sxlate[symidx]);
+ if (type == 0)
+ goto try_parent;
- info = *dp++;
- kind = LCTF_INFO_KIND (fp, info);
- n = LCTF_INFO_VLEN (fp, info);
+ return type;
+ try_parent:
+ if (fp->ctf_parent)
+ return ctf_lookup_by_symbol (fp->ctf_parent, symidx);
+ else
+ return (ctf_set_errno (fp, err));
+}
- if (kind == CTF_K_UNKNOWN && n == 0)
- return (ctf_set_errno (fp, ECTF_NOFUNCDAT));
+/* Given a symbol table index, return the info for the function described
+ by the corresponding entry in the symbol table, which may be a function
+ symbol or may be a data symbol that happens to be a function pointer. */
- if (kind != CTF_K_FUNCTION)
- return (ctf_set_errno (fp, ECTF_CORRUPT));
+int
+ctf_func_info (ctf_dict_t *fp, unsigned long symidx, ctf_funcinfo_t *fip)
+{
+ ctf_id_t type;
- fip->ctc_return = *dp++;
- fip->ctc_argc = n;
- fip->ctc_flags = 0;
+ if ((type = ctf_lookup_by_symbol (fp, symidx)) == CTF_ERR)
+ return -1; /* errno is set for us. */
- if (n != 0 && dp[n - 1] == 0)
- {
- fip->ctc_flags |= CTF_FUNC_VARARG;
- fip->ctc_argc--;
- }
+ if (ctf_type_kind (fp, type) != CTF_K_FUNCTION)
+ return (ctf_set_errno (fp, ECTF_NOTFUNC));
- return 0;
+ return ctf_func_type_info (fp, type, fip);
}
/* Given a symbol table index, return the arguments for the function described
@@ -423,21 +737,15 @@ ctf_func_info (ctf_dict_t *fp, unsigned long symidx, ctf_funcinfo_t *fip)
int
ctf_func_args (ctf_dict_t *fp, unsigned long symidx, uint32_t argc,
- ctf_id_t * argv)
+ ctf_id_t *argv)
{
- const uint32_t *dp;
- ctf_funcinfo_t f;
-
- if (ctf_func_info (fp, symidx, &f) < 0)
- return -1; /* errno is set for us. */
-
- /* The argument data is two uint32_t's past the translation table
- offset: one for the function info, and one for the return type. */
+ ctf_id_t type;
- dp = (uint32_t *) ((uintptr_t) fp->ctf_buf + fp->ctf_sxlate[symidx]) + 2;
+ if ((type = ctf_lookup_by_symbol (fp, symidx)) == CTF_ERR)
+ return -1; /* errno is set for us. */
- for (argc = MIN (argc, f.ctc_argc); argc != 0; argc--)
- *argv++ = *dp++;
+ if (ctf_type_kind (fp, type) != CTF_K_FUNCTION)
+ return (ctf_set_errno (fp, ECTF_NOTFUNC));
- return 0;
+ return ctf_func_type_args (fp, type, argc, argv);
}