/* Type handling functions.
- Copyright (C) 2019-2020 Free Software Foundation, Inc.
+ Copyright (C) 2019-2021 Free Software Foundation, Inc.
This file is part of libctf.
/* Determine whether a type is a parent or a child. */
int
-ctf_type_isparent (ctf_file_t *fp, ctf_id_t id)
+ctf_type_isparent (ctf_dict_t *fp, ctf_id_t id)
{
return (LCTF_TYPE_ISPARENT (fp, id));
}
int
-ctf_type_ischild (ctf_file_t * fp, ctf_id_t id)
+ctf_type_ischild (ctf_dict_t * fp, ctf_id_t id)
{
return (LCTF_TYPE_ISCHILD (fp, id));
}
type, and offset of each member to the specified callback function. */
int
-ctf_member_iter (ctf_file_t *fp, ctf_id_t type, ctf_member_f *func, void *arg)
+ctf_member_iter (ctf_dict_t *fp, ctf_id_t type, ctf_member_f *func, void *arg)
{
- ctf_file_t *ofp = fp;
+ ctf_dict_t *ofp = fp;
const ctf_type_t *tp;
ctf_dtdef_t *dtd;
ssize_t size, increment;
returns -1. */
ssize_t
-ctf_member_next (ctf_file_t *fp, ctf_id_t type, ctf_next_t **it,
+ctf_member_next (ctf_dict_t *fp, ctf_id_t type, ctf_next_t **it,
const char **name, ctf_id_t *membtype)
{
- ctf_file_t *ofp = fp;
+ ctf_dict_t *ofp = fp;
uint32_t kind;
ssize_t offset;
ctf_next_t *i = *it;
integer value of each enum element to the specified callback function. */
int
-ctf_enum_iter (ctf_file_t *fp, ctf_id_t type, ctf_enum_f *func, void *arg)
+ctf_enum_iter (ctf_dict_t *fp, ctf_id_t type, ctf_enum_f *func, void *arg)
{
- ctf_file_t *ofp = fp;
+ ctf_dict_t *ofp = fp;
const ctf_type_t *tp;
const ctf_enum_t *ep;
ctf_dtdef_t *dtd;
enumerand's integer VALue. */
const char *
-ctf_enum_next (ctf_file_t *fp, ctf_id_t type, ctf_next_t **it,
+ctf_enum_next (ctf_dict_t *fp, ctf_id_t type, ctf_next_t **it,
int *val)
{
- ctf_file_t *ofp = fp;
+ ctf_dict_t *ofp = fp;
uint32_t kind;
const char *name;
ctf_next_t *i = *it;
return NULL;
}
-/* Iterate over every root (user-visible) type in the given CTF container.
+/* Iterate over every root (user-visible) type in the given CTF dict.
We pass the type ID of each type to the specified callback function.
Does not traverse parent types: you have to do that explicitly. This is by
of a single parent. */
int
-ctf_type_iter (ctf_file_t *fp, ctf_type_f *func, void *arg)
+ctf_type_iter (ctf_dict_t *fp, ctf_type_f *func, void *arg)
{
ctf_id_t id, max = fp->ctf_typemax;
int rc, child = (fp->ctf_flags & LCTF_CHILD);
return 0;
}
-/* Iterate over every type in the given CTF container, user-visible or not.
+/* Iterate over every type in the given CTF dict, user-visible or not.
We pass the type ID of each type to the specified callback function.
Does not traverse parent types: you have to do that explicitly. This is by
of a single parent. */
int
-ctf_type_iter_all (ctf_file_t *fp, ctf_type_all_f *func, void *arg)
+ctf_type_iter_all (ctf_dict_t *fp, ctf_type_all_f *func, void *arg)
{
ctf_id_t id, max = fp->ctf_typemax;
int rc, child = (fp->ctf_flags & LCTF_CHILD);
return 0;
}
-/* Iterate over every type in the given CTF container, optionally including
+/* Iterate over every type in the given CTF dict, optionally including
non-user-visible types, returning each type ID and hidden flag in turn.
Returns CTF_ERR on end of iteration or error.
of a single parent. */
ctf_id_t
-ctf_type_next (ctf_file_t *fp, ctf_next_t **it, int *flag, int want_hidden)
+ctf_type_next (ctf_dict_t *fp, ctf_next_t **it, int *flag, int want_hidden)
{
ctf_next_t *i = *it;
return ctf_set_errno (fp, ECTF_NEXT_END);
}
-/* Iterate over every variable in the given CTF container, in arbitrary order.
+/* Iterate over every variable in the given CTF dict, in arbitrary order.
We pass the name of each variable to the specified callback function. */
int
-ctf_variable_iter (ctf_file_t *fp, ctf_variable_f *func, void *arg)
+ctf_variable_iter (ctf_dict_t *fp, ctf_variable_f *func, void *arg)
{
int rc;
return 0;
}
-/* Iterate over every variable in the given CTF container, in arbitrary order,
+/* Iterate over every variable in the given CTF dict, in arbitrary order,
returning the name and type of each variable in turn. The name argument is
not optional. Returns CTF_ERR on end of iteration or error. */
ctf_id_t
-ctf_variable_next (ctf_file_t *fp, ctf_next_t **it, const char **name)
+ctf_variable_next (ctf_dict_t *fp, ctf_next_t **it, const char **name)
{
ctf_next_t *i = *it;
Does not drill down through slices to their contained type. */
ctf_id_t
-ctf_type_resolve (ctf_file_t *fp, ctf_id_t type)
+ctf_type_resolve (ctf_dict_t *fp, ctf_id_t type)
{
ctf_id_t prev = type, otype = type;
- ctf_file_t *ofp = fp;
+ ctf_dict_t *ofp = fp;
const ctf_type_t *tp;
if (type == 0)
if (tp->ctt_type == type || tp->ctt_type == otype
|| tp->ctt_type == prev)
{
- ctf_dprintf ("type %ld cycle detected\n", otype);
+ ctf_err_warn (ofp, 0, ECTF_CORRUPT, _("type %lx cycle detected"),
+ otype);
return (ctf_set_errno (ofp, ECTF_CORRUPT));
}
prev = type;
type. */
ctf_id_t
-ctf_type_resolve_unsliced (ctf_file_t *fp, ctf_id_t type)
+ctf_type_resolve_unsliced (ctf_dict_t *fp, ctf_id_t type)
{
const ctf_type_t *tp;
return type;
}
+/* 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)
+{
+ if ((fp->ctf_flags & LCTF_CHILD) && LCTF_TYPE_ISPARENT (fp, type))
+ return fp->ctf_parent;
+
+ return fp;
+}
+
/* Look up a name in the given name table, in the appropriate hash given the
kind of the identifier. The name is a raw, undecorated identifier. */
-ctf_id_t ctf_lookup_by_rawname (ctf_file_t *fp, int kind, const char *name)
+ctf_id_t ctf_lookup_by_rawname (ctf_dict_t *fp, int kind, const char *name)
{
return ctf_lookup_by_rawhash (fp, ctf_name_table (fp, kind), name);
}
readability state of the dictionary. The name is a raw, undecorated
identifier. */
-ctf_id_t ctf_lookup_by_rawhash (ctf_file_t *fp, ctf_names_t *np, const char *name)
+ctf_id_t ctf_lookup_by_rawhash (ctf_dict_t *fp, ctf_names_t *np, const char *name)
{
ctf_id_t id;
if (fp->ctf_flags & LCTF_RDWR)
- id = (ctf_id_t) ctf_dynhash_lookup (np->ctn_writable, name);
+ id = (ctf_id_t) (uintptr_t) ctf_dynhash_lookup (np->ctn_writable, name);
else
id = ctf_hash_lookup_type (np->ctn_readonly, fp, name);
return id;
string. */
char *
-ctf_type_aname (ctf_file_t *fp, ctf_id_t type)
+ctf_type_aname (ctf_dict_t *fp, ctf_id_t type)
{
ctf_decl_t cd;
ctf_decl_node_t *cdp;
for (cdp = ctf_list_next (&cd.cd_nodes[prec]);
cdp != NULL; cdp = ctf_list_next (cdp))
{
- ctf_file_t *rfp = fp;
+ ctf_dict_t *rfp = fp;
const ctf_type_t *tp = ctf_lookup_by_id (&rfp, cdp->cd_type);
const char *name = ctf_strptr (rfp, tp->ctt_name);
ctf_decl_sprintf (&cd, "[%u]", cdp->cd_n);
break;
case CTF_K_FUNCTION:
- ctf_decl_sprintf (&cd, "()");
+ {
+ size_t i;
+ ctf_funcinfo_t fi;
+ ctf_id_t *argv = NULL;
+
+ if (ctf_func_type_info (rfp, cdp->cd_type, &fi) < 0)
+ goto err; /* errno is set for us. */
+
+ if ((argv = calloc (fi.ctc_argc, sizeof (ctf_id_t *))) == NULL)
+ {
+ ctf_set_errno (rfp, errno);
+ goto err;
+ }
+
+ if (ctf_func_type_args (rfp, cdp->cd_type,
+ fi.ctc_argc, argv) < 0)
+ goto err; /* errno is set for us. */
+
+ ctf_decl_sprintf (&cd, "(*) (");
+ for (i = 0; i < fi.ctc_argc; i++)
+ {
+ char *arg = ctf_type_aname (rfp, argv[i]);
+
+ if (arg == NULL)
+ goto err; /* errno is set for us. */
+ ctf_decl_sprintf (&cd, "%s", arg);
+ free (arg);
+
+ if ((i < fi.ctc_argc - 1)
+ || (fi.ctc_flags & CTF_FUNC_VARARG))
+ ctf_decl_sprintf (&cd, ", ");
+ }
+
+ if (fi.ctc_flags & CTF_FUNC_VARARG)
+ ctf_decl_sprintf (&cd, "...");
+ ctf_decl_sprintf (&cd, ")");
+
+ free (argv);
+ break;
+
+ err:
+ free (argv);
+ ctf_decl_fini (&cd);
+ return NULL;
+ }
break;
case CTF_K_STRUCT:
case CTF_K_FORWARD:
the actual number of bytes (not including \0) needed to format the name. */
ssize_t
-ctf_type_lname (ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
+ctf_type_lname (ctf_dict_t *fp, ctf_id_t type, char *buf, size_t len)
{
char *str = ctf_type_aname (fp, type);
size_t slen;
is too small, return NULL: the ECTF_NAMELEN error is set on 'fp' for us. */
char *
-ctf_type_name (ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
+ctf_type_name (ctf_dict_t *fp, ctf_id_t type, char *buf, size_t len)
{
ssize_t rv = ctf_type_lname (fp, type, buf, len);
return (rv >= 0 && (size_t) rv < len ? buf : NULL);
}
/* Lookup the given type ID and return its raw, unadorned, undecorated name.
- The name will live as long as its ctf_file_t does. */
+ The name will live as long as its ctf_dict_t does. */
const char *
-ctf_type_name_raw (ctf_file_t *fp, ctf_id_t type)
+ctf_type_name_raw (ctf_dict_t *fp, ctf_id_t type)
{
const ctf_type_t *tp;
new dynamically-allocated string. */
char *
-ctf_type_aname_raw (ctf_file_t *fp, ctf_id_t type)
+ctf_type_aname_raw (ctf_dict_t *fp, ctf_id_t type)
{
const char *name = ctf_type_name_raw (fp, type);
of the type storage in bytes. */
ssize_t
-ctf_type_size (ctf_file_t *fp, ctf_id_t type)
+ctf_type_size (ctf_dict_t *fp, ctf_id_t type)
{
const ctf_type_t *tp;
ssize_t size;
XXX may need arch-dependent attention. */
ssize_t
-ctf_type_align (ctf_file_t *fp, ctf_id_t type)
+ctf_type_align (ctf_dict_t *fp, ctf_id_t type)
{
const ctf_type_t *tp;
- ctf_file_t *ofp = fp;
+ ctf_dict_t *ofp = fp;
int kind;
if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
/* Return the kind (CTF_K_* constant) for the specified type ID. */
int
-ctf_type_kind_unsliced (ctf_file_t *fp, ctf_id_t type)
+ctf_type_kind_unsliced (ctf_dict_t *fp, ctf_id_t type)
{
const ctf_type_t *tp;
Slices are considered to be of the same kind as the type sliced. */
int
-ctf_type_kind (ctf_file_t *fp, ctf_id_t type)
+ctf_type_kind (ctf_dict_t *fp, ctf_id_t type)
{
int kind;
/* Return the kind of this type, except, for forwards, return the kind of thing
this is a forward to. */
int
-ctf_type_kind_forwarded (ctf_file_t *fp, ctf_id_t type)
+ctf_type_kind_forwarded (ctf_dict_t *fp, ctf_id_t type)
{
int kind;
const ctf_type_t *tp;
then return the ID of the type to which it refers. */
ctf_id_t
-ctf_type_reference (ctf_file_t *fp, ctf_id_t type)
+ctf_type_reference (ctf_dict_t *fp, ctf_id_t type)
{
- ctf_file_t *ofp = fp;
+ ctf_dict_t *ofp = fp;
const ctf_type_t *tp;
if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
instead. This helps with cases where the CTF data includes "struct foo *"
but not "foo_t *" and the user accesses "foo_t *" in the debugger.
- XXX what about parent containers? */
+ XXX what about parent dicts? */
ctf_id_t
-ctf_type_pointer (ctf_file_t *fp, ctf_id_t type)
+ctf_type_pointer (ctf_dict_t *fp, ctf_id_t type)
{
- ctf_file_t *ofp = fp;
+ ctf_dict_t *ofp = fp;
ctf_id_t ntype;
if (ctf_lookup_by_id (&fp, type) == NULL)
/* Return the encoding for the specified INTEGER or FLOAT. */
int
-ctf_type_encoding (ctf_file_t *fp, ctf_id_t type, ctf_encoding_t *ep)
+ctf_type_encoding (ctf_dict_t *fp, ctf_id_t type, ctf_encoding_t *ep)
{
- ctf_file_t *ofp = fp;
+ ctf_dict_t *ofp = fp;
ctf_dtdef_t *dtd;
const ctf_type_t *tp;
ssize_t increment;
}
int
-ctf_type_cmp (ctf_file_t *lfp, ctf_id_t ltype, ctf_file_t *rfp,
+ctf_type_cmp (ctf_dict_t *lfp, ctf_id_t ltype, ctf_dict_t *rfp,
ctf_id_t rtype)
{
int rval;
unions) member count. */
int
-ctf_type_compat (ctf_file_t *lfp, ctf_id_t ltype,
- ctf_file_t *rfp, ctf_id_t rtype)
+ctf_type_compat (ctf_dict_t *lfp, ctf_id_t ltype,
+ ctf_dict_t *rfp, ctf_id_t rtype)
{
const ctf_type_t *ltp, *rtp;
ctf_encoding_t le, re;
enumerators in an ENUM. */
int
-ctf_member_count (ctf_file_t *fp, ctf_id_t type)
+ctf_member_count (ctf_dict_t *fp, ctf_id_t type)
{
- ctf_file_t *ofp = fp;
+ ctf_dict_t *ofp = fp;
const ctf_type_t *tp;
uint32_t kind;
/* Return the type and offset for a given member of a STRUCT or UNION. */
int
-ctf_member_info (ctf_file_t *fp, ctf_id_t type, const char *name,
+ctf_member_info (ctf_dict_t *fp, ctf_id_t type, const char *name,
ctf_membinfo_t *mip)
{
- ctf_file_t *ofp = fp;
+ ctf_dict_t *ofp = fp;
const ctf_type_t *tp;
ctf_dtdef_t *dtd;
ssize_t size, increment;
/* Return the array type, index, and size information for the specified ARRAY. */
int
-ctf_array_info (ctf_file_t *fp, ctf_id_t type, ctf_arinfo_t *arp)
+ctf_array_info (ctf_dict_t *fp, ctf_id_t type, ctf_arinfo_t *arp)
{
- ctf_file_t *ofp = fp;
+ ctf_dict_t *ofp = fp;
const ctf_type_t *tp;
const ctf_array_t *ap;
const ctf_dtdef_t *dtd;
matching name can be found. Otherwise NULL is returned. */
const char *
-ctf_enum_name (ctf_file_t *fp, ctf_id_t type, int value)
+ctf_enum_name (ctf_dict_t *fp, ctf_id_t type, int value)
{
- ctf_file_t *ofp = fp;
+ ctf_dict_t *ofp = fp;
const ctf_type_t *tp;
const ctf_enum_t *ep;
const ctf_dtdef_t *dtd;
matching name can be found. Otherwise CTF_ERR is returned. */
int
-ctf_enum_value (ctf_file_t * fp, ctf_id_t type, const char *name, int *valp)
+ctf_enum_value (ctf_dict_t * fp, ctf_id_t type, const char *name, int *valp)
{
- ctf_file_t *ofp = fp;
+ ctf_dict_t *ofp = fp;
const ctf_type_t *tp;
const ctf_enum_t *ep;
const ctf_dtdef_t *dtd;
arg counts for that function. */
int
-ctf_func_type_info (ctf_file_t *fp, ctf_id_t type, ctf_funcinfo_t *fip)
+ctf_func_type_info (ctf_dict_t *fp, ctf_id_t type, ctf_funcinfo_t *fip)
{
const ctf_type_t *tp;
uint32_t kind;
function. */
int
-ctf_func_type_args (ctf_file_t *fp, ctf_id_t type, uint32_t argc, ctf_id_t *argv)
+ctf_func_type_args (ctf_dict_t *fp, ctf_id_t type, uint32_t argc, ctf_id_t *argv)
{
const ctf_type_t *tp;
const uint32_t *args;
returns non-zero, we abort and percolate the error code back up to the top. */
static int
-ctf_type_rvisit (ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func,
+ctf_type_rvisit (ctf_dict_t *fp, ctf_id_t type, ctf_visit_f *func,
void *arg, const char *name, unsigned long offset, int depth)
{
ctf_id_t otype = type;
/* Recursively visit the members of any type. We pass the name, member
type, and offset of each member to the specified callback function. */
int
-ctf_type_visit (ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg)
+ctf_type_visit (ctf_dict_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg)
{
return (ctf_type_rvisit (fp, type, func, arg, "", 0, 0));
}