forked from Imagelibrary/binutils-gdb
libctf, create, types: type and decl tags
These are a little more fiddly than previous kinds, because their namespacing rules are odd: they have names (so presumably we want an API to look them up by name), but the names are not unique (they don't need to be, because they are not entities you can refer to from C), so many distinct tags in the same TU can have the same name. Type tags only refer to a type ID: decl tags refer to a specific function parameter or structure member via a zero-indexed "component index". The name tables for these things are a hash of name to a set of type IDs; rather different from all the other named entities in libctf. As a consequence, they can presently be looked up only using their own dedicated functions, not using ctf_lookup_by_name et al. (It's not clear if this restriction could ever be lifted: ctf_lookup_by_name and friends return a type ID, not a set of them.) They are similar enough to each other that we can at least have one function to look up both type and decl tags if you don't care about their component_idx and only want a type ID: ctf_tag. (And one to iterate over them, ctf_tag_next). (A caveat: because tags aren't widely used or generated yet, much of this is more or less untested and/or supposition and will need testing later.) New API, more or less the minimum needed because it's not entirely clear how these things will be used: +ctf_id_t ctf_tag (ctf_dict_t *, ctf_id_t tag); +ctf_id_t ctf_decl_tag (ctf_dict_t *, ctf_id_t decl_tag, + int64_t *component_idx); +ctf_id_t ctf_tag_next (ctf_dict_t *, const char *tag, ctf_next_t **); +ctf_id_t ctf_add_type_tag (ctf_dict_t *, uint32_t, ctf_id_t, const char *); +ctf_id_t ctf_add_decl_type_tag (ctf_dict_t *, uint32_t, ctf_id_t, const char *); +ctf_id_t ctf_add_decl_tag (ctf_dict_t *, uint32_t, ctf_id_t, const char *, + int component_idx);
This commit is contained in:
@@ -272,6 +272,9 @@ ctf_name_table (ctf_dict_t *fp, int kind)
|
||||
case CTF_K_ENUM:
|
||||
case CTF_K_ENUM64:
|
||||
return fp->ctf_enums;
|
||||
case CTF_K_TYPE_TAG:
|
||||
case CTF_K_DECL_TAG:
|
||||
return fp->ctf_tags;
|
||||
case CTF_K_DATASEC:
|
||||
return fp->ctf_datasecs;
|
||||
default:
|
||||
@@ -279,6 +282,37 @@ ctf_name_table (ctf_dict_t *fp, int kind)
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ctf_insert_type_decl_tag (ctf_dict_t *fp, ctf_id_t type, const char *name,
|
||||
int kind)
|
||||
{
|
||||
ctf_dynset_t *types;
|
||||
ctf_dynhash_t *h = ctf_name_table (fp, kind);
|
||||
int err;
|
||||
|
||||
if ((types = ctf_dynhash_lookup (h, name)) == NULL)
|
||||
{
|
||||
types = ctf_dynset_create (htab_hash_pointer, htab_eq_pointer, NULL);
|
||||
|
||||
if (!types)
|
||||
return (ctf_set_errno (fp, ENOMEM));
|
||||
|
||||
err = ctf_dynhash_cinsert (h, name, types);
|
||||
if (err != 0)
|
||||
{
|
||||
err *= -1;
|
||||
return (ctf_set_errno (fp, err));
|
||||
}
|
||||
}
|
||||
|
||||
if ((err = ctf_dynset_insert (types, (void *) (uintptr_t) type)) != 0)
|
||||
{
|
||||
err *= -1;
|
||||
return (ctf_set_errno (fp, err));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ctf_dtd_insert (ctf_dict_t *fp, ctf_dtdef_t *dtd, int flag, int kind)
|
||||
{
|
||||
@@ -287,17 +321,25 @@ ctf_dtd_insert (ctf_dict_t *fp, ctf_dtdef_t *dtd, int flag, int kind)
|
||||
dtd) < 0)
|
||||
return ctf_set_errno (fp, ENOMEM);
|
||||
|
||||
if (flag == CTF_ADD_ROOT && dtd->dtd_data.ctt_name
|
||||
&& (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL)
|
||||
if (flag == CTF_ADD_ROOT && dtd->dtd_data->ctt_name
|
||||
&& (name = ctf_strraw (fp, dtd->dtd_data->ctt_name)) != NULL)
|
||||
{
|
||||
if (ctf_dynhash_insert (ctf_name_table (fp, kind),
|
||||
(char *) name, (void *) (uintptr_t)
|
||||
dtd->dtd_type) < 0)
|
||||
/* Type and decl tags have unusual name tables, since their names are not
|
||||
unique. */
|
||||
|
||||
if (kind != CTF_K_TYPE_TAG && kind != CTF_K_DECL_TAG)
|
||||
{
|
||||
ctf_dynhash_remove (fp->ctf_dthash, (void *) (uintptr_t)
|
||||
dtd->dtd_type);
|
||||
return ctf_set_errno (fp, ENOMEM);
|
||||
if (ctf_dynhash_insert (ctf_name_table (fp, kind),
|
||||
(char *) name, (void *) (uintptr_t)
|
||||
dtd->dtd_type) < 0)
|
||||
{
|
||||
ctf_dynhash_remove (fp->ctf_dthash, (void *) (uintptr_t)
|
||||
dtd->dtd_type);
|
||||
return ctf_set_errno (fp, ENOMEM);
|
||||
}
|
||||
}
|
||||
else if (ctf_insert_type_decl_tag (fp, dtd->dtd_type, name, kind) < 0)
|
||||
return -1; /* errno is set for us. */
|
||||
}
|
||||
ctf_list_append (&fp->ctf_dtdefs, dtd);
|
||||
return 0;
|
||||
@@ -886,6 +928,125 @@ ctf_set_array (ctf_dict_t *fp, ctf_id_t type, const ctf_arinfo_t *arp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Add a type or decl tag applying to some whole type, or to some
|
||||
component of a type. Component -1 is a whole type. */
|
||||
|
||||
static ctf_id_t
|
||||
ctf_add_tag (ctf_dict_t *fp, uint32_t flag, ctf_id_t type, const char *tag,
|
||||
int is_decl, int32_t component_idx)
|
||||
{
|
||||
ctf_dtdef_t *dtd;
|
||||
size_t vlen_size = 0;
|
||||
int kind = is_decl ? CTF_K_DECL_TAG : CTF_K_TYPE_TAG;
|
||||
int ref_kind = ctf_type_kind (fp, type);
|
||||
|
||||
if (component_idx < -1)
|
||||
return (ctf_set_typed_errno (fp, ECTF_BADCOMPONENT));
|
||||
|
||||
if (is_decl)
|
||||
{
|
||||
vlen_size = sizeof (ctf_decl_tag_t);
|
||||
|
||||
/* Whole-type declarations. */
|
||||
|
||||
if (component_idx == 0)
|
||||
{
|
||||
switch (ref_kind)
|
||||
{
|
||||
case CTF_K_TYPEDEF:
|
||||
case CTF_K_STRUCT:
|
||||
case CTF_K_UNION:
|
||||
case CTF_K_VAR:
|
||||
/* TODO: support addition and querying on CTF_K_FUNCTION too, chasing back
|
||||
to relevant CTF_K_FUNC_LINKAGEs. */
|
||||
case CTF_K_FUNC_LINKAGE:
|
||||
break;
|
||||
default:
|
||||
return (ctf_set_typed_errno (fp, ECTF_BADID));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (component_idx != -1)
|
||||
{
|
||||
ctf_id_t func_type;
|
||||
|
||||
/* Within-type declarations. */
|
||||
|
||||
switch (ref_kind)
|
||||
{
|
||||
case CTF_K_STRUCT:
|
||||
case CTF_K_UNION:
|
||||
|
||||
if (component_idx >= ctf_member_count (fp, type))
|
||||
return (ctf_set_typed_errno (fp, ECTF_BADCOMPONENT));
|
||||
break;
|
||||
|
||||
case CTF_K_FUNC_LINKAGE:
|
||||
if ((func_type = ctf_type_reference (fp, type)) == CTF_ERR)
|
||||
return (ctf_set_typed_errno (fp, ECTF_BADID));
|
||||
/* FALLTHRU */
|
||||
|
||||
case CTF_K_FUNCTION:
|
||||
{
|
||||
ctf_funcinfo_t fi;
|
||||
|
||||
if (ctf_func_type_info (fp, func_type, &fi) < 0)
|
||||
return -1; /* errno is set for us. */
|
||||
|
||||
if ((size_t) component_idx >= fi.ctc_argc)
|
||||
return (ctf_set_typed_errno (fp, ECTF_BADCOMPONENT));
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return (ctf_set_typed_errno (fp, ECTF_BADCOMPONENT));
|
||||
}
|
||||
}
|
||||
|
||||
if (tag == NULL || tag[0] == '\0')
|
||||
return (ctf_set_typed_errno (fp, ECTF_NONAME));
|
||||
|
||||
if ((dtd = ctf_add_generic (fp, flag, tag, kind, 0, vlen_size,
|
||||
0, NULL)) == NULL)
|
||||
return CTF_ERR; /* errno is set for us. */
|
||||
|
||||
dtd->dtd_data->ctt_info = CTF_TYPE_INFO (kind, flag, 0);
|
||||
dtd->dtd_data->ctt_type = (uint32_t) type;
|
||||
|
||||
if (is_decl)
|
||||
{
|
||||
ctf_decl_tag_t *vlen = (ctf_decl_tag_t *) dtd->dtd_vlen;
|
||||
vlen->cdt_component_idx = component_idx;
|
||||
}
|
||||
|
||||
return dtd->dtd_type;
|
||||
}
|
||||
|
||||
/* Create a type tag. */
|
||||
|
||||
ctf_id_t
|
||||
ctf_add_type_tag (ctf_dict_t *fp, uint32_t flag, ctf_id_t type, const char *tag)
|
||||
{
|
||||
return ctf_add_tag (fp, flag, type, tag, 0, -1);
|
||||
}
|
||||
|
||||
/* Create a decl tag applied to an entire type. */
|
||||
|
||||
ctf_id_t
|
||||
ctf_add_decl_type_tag (ctf_dict_t *fp, uint32_t flag, ctf_id_t type, const char *tag)
|
||||
{
|
||||
return ctf_add_tag (fp, flag, type, tag, 1, -1);
|
||||
}
|
||||
|
||||
/* Create a decl tag applied to one element of a type.
|
||||
component_idx must be >= 0. */
|
||||
ctf_id_t
|
||||
ctf_add_decl_tag (ctf_dict_t *fp, uint32_t flag, ctf_id_t type, const char *tag,
|
||||
int component_idx)
|
||||
{
|
||||
return ctf_add_tag (fp, flag, type, tag, 1, component_idx);
|
||||
}
|
||||
|
||||
ctf_id_t
|
||||
ctf_add_function (ctf_dict_t *fp, uint32_t flag,
|
||||
const ctf_funcinfo_t *ctc, const ctf_id_t *argv,
|
||||
|
||||
Reference in New Issue
Block a user