forked from Imagelibrary/binutils-gdb
libctf: CTFv4: type opening
The majority of this commit rejigs the core type table opening code for CTFv4: there are a few ancillary bits it drags in, indicated below. The internal definition of a child dict (that may not have type or string lookups performed in it until ctf_open time) used to be 'has a cth_parent_name', but since BTF doesn't have one of those at all, we add an additional check: a dict the first byte of whose strtab is not 0 must be a child. (If *either* is true, this is a child dict, which allows for the possibility of CTF dicts with non-deduplicated strtabs -- thus with leading \0's -- to exist in future.) The initial sweep through the type table in init_static_types (to size the name-table lookup hashes) also now checks for various types which indicate that this must be a CTF dict, in addition to being adjusted to cater for new CTFv4 representations of things like forwards. (At this early stage, we cannot rely on the functions in ctf-type.c to abstract over this for us.) We make some new hashtables for new namespace-like things: datasecs and type and decl tags. The main name-population loop in init_static_types_names_internal takes prefixes into account, looking for the name on the suffix type (where the name is always found). LSTRUCT handling is removed (they no longer exist); ENUM64s, enum forwards, VARs, datasecs, and type and decl tags get their names suitably populated. Some buggy code which tried to populate the name tables for cvr-quals (which are nameless) was dropped. We add an extra pass which traverses all datasecs and keeps track of which datasec each var is instantiated in (if any) in a new ctf_var_datasecs hash table. (This uses a number of type-querying functions which don't yet exist: they'll be added in the upcoming commits.) We handle the type 0 == void case by pointing the first element of ctf_txlate at a type read in named "void" (making type 0 an alias to it), or, if one doesn't exist, creating a new one (outside the type table and dtd arrays), and pointing type 0 at that. Since it is numbered 0 and not in the type table or dtd arrays, it will never be written out at serialization time, but since it is *present*, libctf consumers who expect the void type to have an integral definition rather than being a magic number will get what they expect.
This commit is contained in:
@@ -541,9 +541,10 @@ extern ctf_id_t ctf_lookup_by_symbol_name (ctf_dict_t *, const char *);
|
|||||||
extern ctf_id_t ctf_symbol_next (ctf_dict_t *, ctf_next_t **,
|
extern ctf_id_t ctf_symbol_next (ctf_dict_t *, ctf_next_t **,
|
||||||
const char **name, int functions);
|
const char **name, int functions);
|
||||||
|
|
||||||
/* Look up a type by name: some simple C type parsing is done, but this is by no
|
/* Look up a type or variable by name: some simple C type parsing is done, but
|
||||||
means comprehensive. Structures, unions and enums need "struct ", "union "
|
this is by no means comprehensive. Structures, unions and enums need "struct
|
||||||
or "enum " on the front, as usual in C. */
|
", "union " or "enum " on the front, as usual in C. Some prefixes not seen
|
||||||
|
in C exist as well: datasecs use "datasec ". */
|
||||||
|
|
||||||
extern ctf_id_t ctf_lookup_by_name (ctf_dict_t *, const char *);
|
extern ctf_id_t ctf_lookup_by_name (ctf_dict_t *, const char *);
|
||||||
|
|
||||||
|
|||||||
@@ -106,14 +106,21 @@ ctf_grow_vlen (ctf_dict_t *fp, ctf_dtdef_t *dtd, size_t vlen)
|
|||||||
ctf_dict_t *
|
ctf_dict_t *
|
||||||
ctf_create (int *errp)
|
ctf_create (int *errp)
|
||||||
{
|
{
|
||||||
static const ctf_header_t hdr = { .cth_preamble = { CTF_MAGIC, CTF_VERSION, 0 } };
|
static ctf_header_t hdr =
|
||||||
|
{
|
||||||
|
.btf.bth_preamble = { CTF_BTF_MAGIC, CTF_BTF_VERSION, 0 },
|
||||||
|
.btf.bth_hdr_len = sizeof (ctf_btf_header_t),
|
||||||
|
};
|
||||||
|
|
||||||
ctf_dynhash_t *structs = NULL, *unions = NULL, *enums = NULL, *names = NULL;
|
ctf_dynhash_t *structs = NULL, *unions = NULL, *enums = NULL, *names = NULL;
|
||||||
|
ctf_dynhash_t *datasecs = NULL, *tags = NULL;
|
||||||
ctf_sect_t cts;
|
ctf_sect_t cts;
|
||||||
ctf_dict_t *fp;
|
ctf_dict_t *fp;
|
||||||
|
|
||||||
libctf_init_debug();
|
libctf_init_debug();
|
||||||
|
|
||||||
|
hdr.cth_preamble.ctp_magic_version = (CTFv4_MAGIC << 16) | CTF_VERSION;
|
||||||
|
|
||||||
structs = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
|
structs = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
unions = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
|
unions = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
|
||||||
@@ -122,7 +129,11 @@ ctf_create (int *errp)
|
|||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
names = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
|
names = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
if (!structs || !unions || !enums || !names)
|
datasecs = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
|
||||||
|
NULL, NULL);
|
||||||
|
tags = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
|
||||||
|
NULL, (ctf_hash_free_fun) ctf_dynset_destroy);
|
||||||
|
if (!structs || !unions || !enums || !names || !datasecs || !tags)
|
||||||
{
|
{
|
||||||
ctf_set_open_errno (errp, EAGAIN);
|
ctf_set_open_errno (errp, EAGAIN);
|
||||||
goto err;
|
goto err;
|
||||||
@@ -142,10 +153,14 @@ ctf_create (int *errp)
|
|||||||
ctf_dynhash_destroy (fp->ctf_unions);
|
ctf_dynhash_destroy (fp->ctf_unions);
|
||||||
ctf_dynhash_destroy (fp->ctf_enums);
|
ctf_dynhash_destroy (fp->ctf_enums);
|
||||||
ctf_dynhash_destroy (fp->ctf_names);
|
ctf_dynhash_destroy (fp->ctf_names);
|
||||||
|
ctf_dynhash_destroy (fp->ctf_datasecs);
|
||||||
|
ctf_dynhash_destroy (fp->ctf_tags);
|
||||||
fp->ctf_structs = structs;
|
fp->ctf_structs = structs;
|
||||||
fp->ctf_unions = unions;
|
fp->ctf_unions = unions;
|
||||||
fp->ctf_enums = enums;
|
fp->ctf_enums = enums;
|
||||||
fp->ctf_names = names;
|
fp->ctf_names = names;
|
||||||
|
fp->ctf_datasecs = datasecs;
|
||||||
|
fp->ctf_tags = tags;
|
||||||
fp->ctf_dtoldid = 0;
|
fp->ctf_dtoldid = 0;
|
||||||
fp->ctf_snapshot_lu = 0;
|
fp->ctf_snapshot_lu = 0;
|
||||||
|
|
||||||
@@ -166,6 +181,8 @@ ctf_create (int *errp)
|
|||||||
ctf_dynhash_destroy (unions);
|
ctf_dynhash_destroy (unions);
|
||||||
ctf_dynhash_destroy (enums);
|
ctf_dynhash_destroy (enums);
|
||||||
ctf_dynhash_destroy (names);
|
ctf_dynhash_destroy (names);
|
||||||
|
ctf_dynhash_destroy (datasecs);
|
||||||
|
ctf_dynhash_destroy (tags);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -779,6 +779,12 @@ ctf_dynset_destroy (ctf_dynset_t *hp)
|
|||||||
htab_delete ((struct htab *) hp);
|
htab_delete ((struct htab *) hp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ctf_dynset_destroy_arg (ctf_dynset_t *hp, void *unused _libctf_unused_)
|
||||||
|
{
|
||||||
|
ctf_dynset_destroy (hp);
|
||||||
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
ctf_dynset_lookup (ctf_dynset_t *hp, const void *key)
|
ctf_dynset_lookup (ctf_dynset_t *hp, const void *key)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -385,9 +385,12 @@ struct ctf_dict
|
|||||||
ctf_dynhash_t *ctf_structs; /* Hash table of struct types. */
|
ctf_dynhash_t *ctf_structs; /* Hash table of struct types. */
|
||||||
ctf_dynhash_t *ctf_unions; /* Hash table of union types. */
|
ctf_dynhash_t *ctf_unions; /* Hash table of union types. */
|
||||||
ctf_dynhash_t *ctf_enums; /* Hash table of enum types. */
|
ctf_dynhash_t *ctf_enums; /* Hash table of enum types. */
|
||||||
|
ctf_dynhash_t *ctf_datasecs; /* Hash table of datasecs. */
|
||||||
|
ctf_dynhash_t *ctf_tags; /* Hash table of dynsets of type/decl tags. */
|
||||||
ctf_dynhash_t *ctf_names; /* Hash table of remaining types, plus
|
ctf_dynhash_t *ctf_names; /* Hash table of remaining types, plus
|
||||||
enumeration constants. */
|
enumeration constants. */
|
||||||
ctf_lookup_t ctf_lookups[5]; /* Pointers to nametabs for name lookup. */
|
ctf_lookup_t ctf_lookups[6]; /* Pointers to nametabs for name lookup. */
|
||||||
|
ctf_dynhash_t *ctf_var_datasecs; /* Variable -> datasec mappings. */
|
||||||
ctf_strs_t ctf_str[2]; /* Array of string table base and bounds. */
|
ctf_strs_t ctf_str[2]; /* Array of string table base and bounds. */
|
||||||
ctf_strs_writable_t *ctf_dynstrtab; /* Dynamically allocated string table, if any. */
|
ctf_strs_writable_t *ctf_dynstrtab; /* Dynamically allocated string table, if any. */
|
||||||
ctf_dynhash_t *ctf_str_atoms; /* Hash table of ctf_str_atoms_t. */
|
ctf_dynhash_t *ctf_str_atoms; /* Hash table of ctf_str_atoms_t. */
|
||||||
@@ -412,6 +415,8 @@ struct ctf_dict
|
|||||||
uint32_t *ctf_pptrtab; /* Parent types pointed to by child dicts. */
|
uint32_t *ctf_pptrtab; /* Parent types pointed to by child dicts. */
|
||||||
size_t ctf_pptrtab_len; /* Num types storable in pptrtab currently. */
|
size_t ctf_pptrtab_len; /* Num types storable in pptrtab currently. */
|
||||||
uint32_t ctf_pptrtab_typemax; /* Max child type when pptrtab last updated. */
|
uint32_t ctf_pptrtab_typemax; /* Max child type when pptrtab last updated. */
|
||||||
|
ctf_type_t *ctf_void_type; /* void type, if dynamically constructed. (More
|
||||||
|
space allocated, due to vlen.) */
|
||||||
ctf_dynset_t *ctf_conflicting_enums; /* Tracks enum constants that conflict. */
|
ctf_dynset_t *ctf_conflicting_enums; /* Tracks enum constants that conflict. */
|
||||||
uint32_t *ctf_funcidx_names; /* Name of each function symbol in symtypetab
|
uint32_t *ctf_funcidx_names; /* Name of each function symbol in symtypetab
|
||||||
(if indexed). */
|
(if indexed). */
|
||||||
@@ -707,6 +712,7 @@ extern int ctf_dynset_insert (ctf_dynset_t *, void *);
|
|||||||
extern void ctf_dynset_remove (ctf_dynset_t *, const void *);
|
extern void ctf_dynset_remove (ctf_dynset_t *, const void *);
|
||||||
extern size_t ctf_dynset_elements (const ctf_dynset_t *);
|
extern size_t ctf_dynset_elements (const ctf_dynset_t *);
|
||||||
extern void ctf_dynset_destroy (ctf_dynset_t *);
|
extern void ctf_dynset_destroy (ctf_dynset_t *);
|
||||||
|
extern void ctf_dynset_destroy_arg (ctf_dynset_t *, void *unused);
|
||||||
extern void *ctf_dynset_lookup (ctf_dynset_t *, const void *);
|
extern void *ctf_dynset_lookup (ctf_dynset_t *, const void *);
|
||||||
extern int ctf_dynset_exists (ctf_dynset_t *, const void *key,
|
extern int ctf_dynset_exists (ctf_dynset_t *, const void *key,
|
||||||
const void **orig_key);
|
const void **orig_key);
|
||||||
|
|||||||
@@ -560,7 +560,7 @@ ctf_set_base (ctf_dict_t *fp, const ctf_header_t *hp, unsigned char *base)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
init_static_types_names (ctf_dict_t *fp, ctf_header_t *cth);
|
init_static_types_names (ctf_dict_t *fp, ctf_header_t *cth, int is_btf);
|
||||||
|
|
||||||
/* Populate statically-defined types (those loaded from a saved buffer).
|
/* Populate statically-defined types (those loaded from a saved buffer).
|
||||||
|
|
||||||
@@ -591,50 +591,105 @@ init_static_types (ctf_dict_t *fp, ctf_header_t *cth, int is_btf)
|
|||||||
fp->ctf_provtypemax = (uint32_t) -1;
|
fp->ctf_provtypemax = (uint32_t) -1;
|
||||||
|
|
||||||
/* We determine whether the dict is a child or a parent based on the value of
|
/* We determine whether the dict is a child or a parent based on the value of
|
||||||
cth_parname. */
|
cth_parent_name: for BTF this is not enough, because there is no
|
||||||
|
cth_parent_name: instead, we can check the first byte of the strtab, which
|
||||||
|
is always 0 for parents and never 0 for children. */
|
||||||
|
|
||||||
int child = cth->cth_parname != 0;
|
int child = (cth->cth_parent_name != 0
|
||||||
|
|| (fp->ctf_str[CTF_STRTAB_0].cts_len > 0
|
||||||
|
&& fp->ctf_str[CTF_STRTAB_0].cts_strs[0] != 0));
|
||||||
|
|
||||||
if (fp->ctf_version < CTF_VERSION_4)
|
if (fp->ctf_version < CTF_VERSION_4)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if ((err = upgrade_types (fp, cth)) != 0)
|
if ((err = upgrade_types (fp, cth)) != 0)
|
||||||
return err; /* Upgrade failed. */
|
return err; /* Upgrade failed. */
|
||||||
|
#endif
|
||||||
|
ctf_err_warn (NULL, 0, ECTF_INTERNAL, "Implementation of backward-compatible CTF reading still underway\n");
|
||||||
|
return ECTF_INTERNAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
tbuf = (ctf_type_t *) (fp->ctf_buf + cth->cth_typeoff);
|
tbuf = (ctf_type_t *) (fp->ctf_buf + cth->btf.bth_type_off);
|
||||||
tend = (ctf_type_t *) (fp->ctf_buf + cth->cth_stroff);
|
tend = (ctf_type_t *) ((uintptr_t) tbuf + cth->btf.bth_type_len);
|
||||||
|
|
||||||
/* We make two passes through the entire type section, and one third pass
|
/* We make two passes through the entire type section, and more passes through
|
||||||
through part of it: but only the first is guaranteed to happen at this
|
parts of it: but only the first is guaranteed to happen at this stage. The
|
||||||
stage. The second and third passes require working string lookup, so in
|
later passes require working string lookup, so in child dicts can only
|
||||||
child dicts can only happen at ctf_import time.
|
happen at ctf_import time.
|
||||||
|
|
||||||
|
For prefixed kinds, we are interested in the thing we are prefixing:
|
||||||
|
that is the true type.
|
||||||
|
|
||||||
In this first pass, we count the number of each type and type-like
|
In this first pass, we count the number of each type and type-like
|
||||||
identifier (like enumerators) and the total number of types. */
|
identifier (like enumerators) and the total number of types. */
|
||||||
|
|
||||||
for (tp = tbuf; tp < tend; typemax++)
|
for (tp = tbuf; tp < tend; typemax++)
|
||||||
{
|
{
|
||||||
unsigned short kind = LCTF_INFO_KIND (fp, tp->ctt_info);
|
unsigned short kind = LCTF_INFO_UNPREFIXED_KIND (fp, tp->ctt_info);
|
||||||
unsigned long vlen = LCTF_INFO_VLEN (fp, tp->ctt_info);
|
size_t vlen = LCTF_VLEN (fp, tp);
|
||||||
|
int nonroot = 0;
|
||||||
ssize_t size, increment, vbytes;
|
ssize_t size, increment, vbytes;
|
||||||
|
const ctf_type_t *suffix = tp;
|
||||||
|
|
||||||
(void) ctf_get_ctt_size (fp, tp, &size, &increment);
|
(void) ctf_get_ctt_size (fp, tp, &size, &increment);
|
||||||
vbytes = LCTF_VBYTES (fp, kind, size, vlen);
|
|
||||||
|
/* Go to the first unprefixed type, incrementing all prefixed types'
|
||||||
|
popcounts along the way. If we find a CTF_K_CONFLICTING, stop: these
|
||||||
|
counts are used to increment identifier hashtab sizes, and conflicting
|
||||||
|
types do not appear in identifier hashtabs. */
|
||||||
|
|
||||||
|
while (LCTF_IS_PREFIXED_KIND (kind))
|
||||||
|
{
|
||||||
|
if (is_btf)
|
||||||
|
return ECTF_CORRUPT;
|
||||||
|
|
||||||
|
pop[suffix->ctt_type]++;
|
||||||
|
|
||||||
|
if (kind == CTF_K_CONFLICTING)
|
||||||
|
{
|
||||||
|
nonroot = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
suffix++;
|
||||||
|
if (suffix >= tend)
|
||||||
|
return ECTF_CORRUPT;
|
||||||
|
|
||||||
|
kind = LCTF_INFO_UNPREFIXED_KIND (fp, suffix->ctt_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_btf && kind > CTF_BTF_K_MAX)
|
||||||
|
return ECTF_CORRUPT;
|
||||||
|
|
||||||
|
vbytes = LCTF_VBYTES (fp, suffix, size);
|
||||||
|
|
||||||
if (vbytes < 0)
|
if (vbytes < 0)
|
||||||
return ECTF_CORRUPT;
|
return ECTF_CORRUPT;
|
||||||
|
|
||||||
/* For forward declarations, ctt_type is the CTF_K_* kind for the tag,
|
if (!nonroot)
|
||||||
so bump that population count too. */
|
{
|
||||||
|
/* For forward declarations, the kflag indicates what type to use, so bump
|
||||||
|
that population count too. For enums, vlen 0 indicates a forward, so
|
||||||
|
bump the forward population count. */
|
||||||
if (kind == CTF_K_FORWARD)
|
if (kind == CTF_K_FORWARD)
|
||||||
pop[tp->ctt_type]++;
|
{
|
||||||
|
if (CTF_INFO_KFLAG (suffix->ctt_info))
|
||||||
|
pop[CTF_K_UNION]++;
|
||||||
|
else
|
||||||
|
pop[CTF_K_STRUCT]++;
|
||||||
|
}
|
||||||
|
else if (kind == CTF_K_ENUM && vlen == 0)
|
||||||
|
pop[CTF_K_FORWARD]++;
|
||||||
|
|
||||||
|
if (kind == CTF_K_ENUM || kind == CTF_K_ENUM64)
|
||||||
|
pop_enumerators += vlen;
|
||||||
|
|
||||||
|
pop[kind]++;
|
||||||
|
}
|
||||||
|
|
||||||
tp = (ctf_type_t *) ((uintptr_t) tp + increment + vbytes);
|
tp = (ctf_type_t *) ((uintptr_t) tp + increment + vbytes);
|
||||||
pop[kind]++;
|
|
||||||
|
|
||||||
if (kind == CTF_K_ENUM)
|
|
||||||
pop_enumerators += vlen;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (child)
|
if (child)
|
||||||
@@ -666,11 +721,24 @@ init_static_types (ctf_dict_t *fp, ctf_header_t *cth, int is_btf)
|
|||||||
NULL, NULL, NULL)) == NULL)
|
NULL, NULL, NULL)) == NULL)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
|
|
||||||
|
if ((fp->ctf_datasecs
|
||||||
|
= ctf_dynhash_create_sized (pop[CTF_K_DATASEC], ctf_hash_string,
|
||||||
|
ctf_hash_eq_string,
|
||||||
|
NULL, NULL, NULL)) == NULL)
|
||||||
|
return ENOMEM;
|
||||||
|
|
||||||
|
if ((fp->ctf_tags
|
||||||
|
= ctf_dynhash_create_sized (pop[CTF_K_DECL_TAG] + pop [CTF_K_TYPE_TAG],
|
||||||
|
ctf_hash_string, ctf_hash_eq_string,
|
||||||
|
NULL, (ctf_hash_free_arg_fun) ctf_dynset_destroy_arg,
|
||||||
|
NULL)) == NULL)
|
||||||
|
return ENOMEM;
|
||||||
|
|
||||||
if ((fp->ctf_names
|
if ((fp->ctf_names
|
||||||
= ctf_dynhash_create_sized (pop[CTF_K_UNKNOWN] +
|
= ctf_dynhash_create_sized (pop[CTF_K_UNKNOWN] +
|
||||||
pop[CTF_K_INTEGER] +
|
pop[CTF_K_INTEGER] +
|
||||||
pop[CTF_K_FLOAT] +
|
pop[CTF_K_FLOAT] +
|
||||||
pop[CTF_K_FUNCTION] +
|
pop[CTF_K_FUNC_LINKAGE] +
|
||||||
pop[CTF_K_TYPEDEF] +
|
pop[CTF_K_TYPEDEF] +
|
||||||
pop_enumerators,
|
pop_enumerators,
|
||||||
ctf_hash_string,
|
ctf_hash_string,
|
||||||
@@ -678,6 +746,11 @@ init_static_types (ctf_dict_t *fp, ctf_header_t *cth, int is_btf)
|
|||||||
NULL, NULL, NULL)) == NULL)
|
NULL, NULL, NULL)) == NULL)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
|
|
||||||
|
if ((fp->ctf_var_datasecs
|
||||||
|
= ctf_dynhash_create (htab_hash_pointer, htab_eq_pointer, NULL, NULL))
|
||||||
|
== NULL)
|
||||||
|
return ENOMEM;
|
||||||
|
|
||||||
if ((fp->ctf_conflicting_enums
|
if ((fp->ctf_conflicting_enums
|
||||||
= ctf_dynset_create (htab_hash_string, htab_eq_string, NULL)) == NULL)
|
= ctf_dynset_create (htab_hash_string, htab_eq_string, NULL)) == NULL)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
@@ -698,9 +771,7 @@ init_static_types (ctf_dict_t *fp, ctf_header_t *cth, int is_btf)
|
|||||||
if (fp->ctf_txlate == NULL || fp->ctf_ptrtab == NULL)
|
if (fp->ctf_txlate == NULL || fp->ctf_ptrtab == NULL)
|
||||||
return ENOMEM; /* Memory allocation failed. */
|
return ENOMEM; /* Memory allocation failed. */
|
||||||
|
|
||||||
/* UPTODO: BTF is like v4 here: no string lookups in children, which blocks
|
if (child || cth->cth_parent_strlen != 0)
|
||||||
almost all operations until after ctf_import. */
|
|
||||||
if (child && cth->cth_parent_strlen != 0)
|
|
||||||
{
|
{
|
||||||
fp->ctf_flags |= LCTF_NO_STR;
|
fp->ctf_flags |= LCTF_NO_STR;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -708,17 +779,17 @@ init_static_types (ctf_dict_t *fp, ctf_header_t *cth, int is_btf)
|
|||||||
|
|
||||||
ctf_dprintf ("%u types initialized (other than names)\n", fp->ctf_typemax);
|
ctf_dprintf ("%u types initialized (other than names)\n", fp->ctf_typemax);
|
||||||
|
|
||||||
return init_static_types_names (fp, cth);
|
return init_static_types_names (fp, cth, is_btf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
init_static_types_names_internal (ctf_dict_t *fp, ctf_header_t *cth,
|
init_static_types_names_internal (ctf_dict_t *fp, ctf_header_t *cth, int is_btf,
|
||||||
ctf_dynset_t *all_enums);
|
ctf_dynset_t *all_enums);
|
||||||
|
|
||||||
/* A wrapper to simplify memory allocation. */
|
/* A wrapper to simplify memory allocation. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
init_static_types_names (ctf_dict_t *fp, ctf_header_t *cth)
|
init_static_types_names (ctf_dict_t *fp, ctf_header_t *cth, int is_btf)
|
||||||
{
|
{
|
||||||
ctf_dynset_t *all_enums;
|
ctf_dynset_t *all_enums;
|
||||||
int err;
|
int err;
|
||||||
@@ -727,41 +798,43 @@ init_static_types_names (ctf_dict_t *fp, ctf_header_t *cth)
|
|||||||
NULL)) == NULL)
|
NULL)) == NULL)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
|
|
||||||
err = init_static_types_names_internal (fp, cth, all_enums);
|
err = init_static_types_names_internal (fp, cth, is_btf, all_enums);
|
||||||
ctf_dynset_destroy (all_enums);
|
ctf_dynset_destroy (all_enums);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the parts of the CTF dict whose initialization depends on name
|
static int
|
||||||
lookup. This happens at open time except for child dicts, when (for CTFv4+
|
init_void (ctf_dict_t *fp);
|
||||||
dicts) it happens at ctf_import time instead, because before then the strtab
|
|
||||||
is truncated at the start.
|
/* Initialize the parts of the CTF dict whose initialization depends on name or
|
||||||
|
type lookup. This happens at open time except for child dicts, when (for
|
||||||
|
CTFv4+ dicts) it happens at ctf_import time instead, because before then the
|
||||||
|
strtab and type tables are truncated at the start.
|
||||||
|
|
||||||
As a function largely called at open time, this function does not reliably
|
As a function largely called at open time, this function does not reliably
|
||||||
set the ctf_errno, but instead *returns* the error code. */
|
set the ctf_errno, but instead returns a positive error code. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
init_static_types_names_internal (ctf_dict_t *fp, ctf_header_t *cth,
|
init_static_types_names_internal (ctf_dict_t *fp, ctf_header_t *cth, int is_btf,
|
||||||
ctf_dynset_t *all_enums)
|
ctf_dynset_t *all_enums)
|
||||||
{
|
{
|
||||||
const ctf_type_t *tbuf;
|
ctf_type_t *tbuf, *tend, *tp;
|
||||||
const ctf_type_t *tend;
|
ctf_type_t **xp;
|
||||||
|
|
||||||
const ctf_type_t *tp;
|
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
uint32_t *xp;
|
ctf_id_t type;
|
||||||
|
|
||||||
unsigned long typemax = fp->ctf_typemax;
|
|
||||||
|
|
||||||
ctf_next_t *i = NULL;
|
ctf_next_t *i = NULL;
|
||||||
void *k;
|
void *k;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
int child = cth->cth_parname != 0;
|
/* See init_static_types. */
|
||||||
int nlstructs = 0, nlunions = 0;
|
int child = (cth->cth_parent_name != 0
|
||||||
|
|| (fp->ctf_str[CTF_STRTAB_0].cts_len > 0
|
||||||
|
&& fp->ctf_str[CTF_STRTAB_0].cts_strs[0] != 0));
|
||||||
|
|
||||||
tbuf = (ctf_type_t *) (fp->ctf_buf + cth->cth_typeoff);
|
tbuf = (ctf_type_t *) (fp->ctf_buf + cth->btf.bth_type_off);
|
||||||
tend = (ctf_type_t *) (fp->ctf_buf + cth->cth_stroff);
|
tend = (ctf_type_t *) ((uintptr_t) tbuf + cth->btf.bth_type_len);
|
||||||
|
|
||||||
assert (!(fp->ctf_flags & LCTF_NO_STR));
|
assert (!(fp->ctf_flags & LCTF_NO_STR));
|
||||||
|
|
||||||
@@ -770,30 +843,34 @@ init_static_types_names_internal (ctf_dict_t *fp, ctf_header_t *cth,
|
|||||||
/* In this second pass through the types, we fill in each entry of the type
|
/* In this second pass through the types, we fill in each entry of the type
|
||||||
and pointer tables and add names to the appropriate hashes.
|
and pointer tables and add names to the appropriate hashes.
|
||||||
|
|
||||||
(Not all names are added in this pass, only type names. See below.)
|
(Not all names are added in this pass, only type names. See below.) */
|
||||||
|
|
||||||
Reset ctf_typemax and bump it as we go, but keep it one higher than normal,
|
for (id = 1, tp = tbuf; tp < tend; xp++, id++)
|
||||||
so that the type being read in is considered a valid type and it is at
|
|
||||||
least barely possible to run simple lookups on it: but higher types are
|
|
||||||
not, since their names are not yet known. (It is kept at its standard
|
|
||||||
value before this function is called so that at least some type-related
|
|
||||||
operations work. */
|
|
||||||
|
|
||||||
for (id = 1, fp->ctf_typemax = 1, tp = tbuf; tp < tend; xp++, id++, fp->ctf_typemax++)
|
|
||||||
{
|
{
|
||||||
unsigned short kind = LCTF_INFO_KIND (fp, tp->ctt_info);
|
unsigned short kind = LCTF_KIND (fp, tp);
|
||||||
unsigned short isroot = LCTF_INFO_ISROOT (fp, tp->ctt_info);
|
unsigned short isroot = LCTF_INFO_ISROOT (fp, tp->ctt_info);
|
||||||
unsigned long vlen = LCTF_INFO_VLEN (fp, tp->ctt_info);
|
size_t vlen = LCTF_VLEN (fp, tp);
|
||||||
ssize_t size, increment, vbytes;
|
ssize_t size, increment, vbytes;
|
||||||
|
const ctf_type_t *suffix = tp;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
(void) ctf_get_ctt_size (fp, tp, &size, &increment);
|
/* Prefixed type: pull off the prefixes (for most purposes). (We already
|
||||||
name = ctf_strptr (fp, tp->ctt_name);
|
know the prefixes cannot overflow.) */
|
||||||
/* Cannot fail: shielded by call in loop above. */
|
|
||||||
vbytes = LCTF_VBYTES (fp, kind, size, vlen);
|
|
||||||
|
|
||||||
*xp = (uint32_t) ((uintptr_t) tp - (uintptr_t) fp->ctf_buf);
|
while (LCTF_IS_PREFIXED_INFO (suffix->ctt_info))
|
||||||
|
{
|
||||||
|
if (is_btf)
|
||||||
|
return ECTF_CORRUPT;
|
||||||
|
|
||||||
|
suffix++;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void) ctf_get_ctt_size (fp, tp, &size, &increment);
|
||||||
|
name = ctf_strptr (fp, suffix->ctt_name);
|
||||||
|
/* Cannot fail: shielded by call in init_static_types. */
|
||||||
|
vbytes = LCTF_VBYTES (fp, suffix, size);
|
||||||
|
|
||||||
|
*xp = tp;
|
||||||
|
|
||||||
switch (kind)
|
switch (kind)
|
||||||
{
|
{
|
||||||
@@ -817,7 +894,10 @@ init_static_types_names_internal (ctf_dict_t *fp, ctf_header_t *cth,
|
|||||||
type as long as the new type is zero-offset and has a
|
type as long as the new type is zero-offset and has a
|
||||||
bit-width wider than the existing one, since the native type
|
bit-width wider than the existing one, since the native type
|
||||||
must necessarily have a bit-width at least as wide as any
|
must necessarily have a bit-width at least as wide as any
|
||||||
bitfield based on it. */
|
bitfield based on it.
|
||||||
|
|
||||||
|
BTF floats are more or less useless, having no encoding:
|
||||||
|
the ctf_type_encoding check here suffices to replace them. */
|
||||||
|
|
||||||
if (((existing = ctf_dynhash_lookup_type (fp->ctf_names, name)) == 0)
|
if (((existing = ctf_dynhash_lookup_type (fp->ctf_names, name)) == 0)
|
||||||
|| ctf_type_encoding (fp, existing, &existing_en) != 0
|
|| ctf_type_encoding (fp, existing, &existing_en) != 0
|
||||||
@@ -828,40 +908,62 @@ init_static_types_names_internal (ctf_dict_t *fp, ctf_header_t *cth,
|
|||||||
{
|
{
|
||||||
err = ctf_dynhash_insert_type (fp, fp->ctf_names,
|
err = ctf_dynhash_insert_type (fp, fp->ctf_names,
|
||||||
ctf_index_to_type (fp, id),
|
ctf_index_to_type (fp, id),
|
||||||
tp->ctt_name);
|
suffix->ctt_name);
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
return err * -1;
|
return err * -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case CTF_K_BTF_FLOAT:
|
||||||
|
{
|
||||||
|
ctf_id_t existing;
|
||||||
|
|
||||||
|
if (!isroot)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Don't allow a float to be overwritten by a BTF float. */
|
||||||
|
|
||||||
|
if (((existing = ctf_dynhash_lookup_type (fp->ctf_names, name)) == 0)
|
||||||
|
&& ctf_type_kind (fp, existing) == CTF_K_FLOAT)
|
||||||
|
break;
|
||||||
|
|
||||||
|
err = ctf_dynhash_insert_type (fp, fp->ctf_names,
|
||||||
|
ctf_index_to_type (fp, id),
|
||||||
|
suffix->ctt_name);
|
||||||
|
if (err != 0)
|
||||||
|
return err * -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* These kinds have no name, so do not need interning into any
|
/* These kinds have no name, so do not need interning into any
|
||||||
hashtables. */
|
hashtables. */
|
||||||
case CTF_K_ARRAY:
|
case CTF_K_ARRAY:
|
||||||
case CTF_K_SLICE:
|
case CTF_K_SLICE:
|
||||||
|
case CTF_K_VOLATILE:
|
||||||
|
case CTF_K_CONST:
|
||||||
|
case CTF_K_RESTRICT:
|
||||||
|
case CTF_K_FUNCTION:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CTF_K_FUNCTION:
|
case CTF_K_FUNC_LINKAGE:
|
||||||
if (!isroot)
|
if (!isroot)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
err = ctf_dynhash_insert_type (fp, fp->ctf_names,
|
err = ctf_dynhash_insert_type (fp, fp->ctf_names,
|
||||||
ctf_index_to_type (fp, id),
|
ctf_index_to_type (fp, id),
|
||||||
tp->ctt_name);
|
suffix->ctt_name);
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
return err * -1;
|
return err * -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CTF_K_STRUCT:
|
case CTF_K_STRUCT:
|
||||||
if (size >= CTF_LSTRUCT_THRESH)
|
|
||||||
nlstructs++;
|
|
||||||
|
|
||||||
if (!isroot)
|
if (!isroot)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
err = ctf_dynhash_insert_type (fp, fp->ctf_structs,
|
err = ctf_dynhash_insert_type (fp, fp->ctf_structs,
|
||||||
ctf_index_to_type (fp, id),
|
ctf_index_to_type (fp, id),
|
||||||
tp->ctt_name);
|
suffix->ctt_name);
|
||||||
|
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
return err * -1;
|
return err * -1;
|
||||||
@@ -869,38 +971,45 @@ init_static_types_names_internal (ctf_dict_t *fp, ctf_header_t *cth,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CTF_K_UNION:
|
case CTF_K_UNION:
|
||||||
if (size >= CTF_LSTRUCT_THRESH)
|
|
||||||
nlunions++;
|
|
||||||
|
|
||||||
if (!isroot)
|
if (!isroot)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
err = ctf_dynhash_insert_type (fp, fp->ctf_unions,
|
err = ctf_dynhash_insert_type (fp, fp->ctf_unions,
|
||||||
ctf_index_to_type (fp, id),
|
ctf_index_to_type (fp, id),
|
||||||
tp->ctt_name);
|
suffix->ctt_name);
|
||||||
|
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
return err * -1;
|
return err * -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CTF_K_ENUM:
|
case CTF_K_ENUM:
|
||||||
|
case CTF_K_ENUM64:
|
||||||
{
|
{
|
||||||
if (!isroot)
|
if (!isroot)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* Only insert forward types if the type is not already present. */
|
||||||
|
if (vlen == 0
|
||||||
|
&& ctf_dynhash_lookup_type (ctf_name_table (fp, kind),
|
||||||
|
name) != 0)
|
||||||
|
break;
|
||||||
|
|
||||||
err = ctf_dynhash_insert_type (fp, fp->ctf_enums,
|
err = ctf_dynhash_insert_type (fp, fp->ctf_enums,
|
||||||
ctf_index_to_type (fp, id),
|
ctf_index_to_type (fp, id),
|
||||||
tp->ctt_name);
|
suffix->ctt_name);
|
||||||
|
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
return err * -1;
|
return err * -1;
|
||||||
|
|
||||||
/* Remember all enums for later rescanning. */
|
/* Remember all non-forward enums for later rescanning. */
|
||||||
|
|
||||||
|
if (vlen != 0)
|
||||||
|
{
|
||||||
err = ctf_dynset_insert (all_enums, (void *) (ptrdiff_t)
|
err = ctf_dynset_insert (all_enums, (void *) (ptrdiff_t)
|
||||||
ctf_index_to_type (fp, id));
|
ctf_index_to_type (fp, id));
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
return err * -1;
|
return err * -1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -910,14 +1019,56 @@ init_static_types_names_internal (ctf_dict_t *fp, ctf_header_t *cth,
|
|||||||
|
|
||||||
err = ctf_dynhash_insert_type (fp, fp->ctf_names,
|
err = ctf_dynhash_insert_type (fp, fp->ctf_names,
|
||||||
ctf_index_to_type (fp, id),
|
ctf_index_to_type (fp, id),
|
||||||
tp->ctt_name);
|
suffix->ctt_name);
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
return err * -1;
|
return err * -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CTF_K_VAR:
|
||||||
|
if (!isroot)
|
||||||
|
break;
|
||||||
|
|
||||||
|
err = ctf_dynhash_insert_type (fp, fp->ctf_names,
|
||||||
|
ctf_index_to_type (fp, id),
|
||||||
|
suffix->ctt_name);
|
||||||
|
if (err != 0)
|
||||||
|
return err * -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CTF_K_DATASEC:
|
||||||
|
if (!isroot)
|
||||||
|
break;
|
||||||
|
|
||||||
|
err = ctf_dynhash_insert_type (fp, fp->ctf_datasecs,
|
||||||
|
ctf_index_to_type (fp, id),
|
||||||
|
suffix->ctt_name);
|
||||||
|
if (err != 0)
|
||||||
|
return err * -1;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CTF_K_DECL_TAG:
|
||||||
|
case CTF_K_TYPE_TAG:
|
||||||
|
{
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
if ((str = ctf_strptr_validate (fp, suffix->ctt_name)) == NULL)
|
||||||
|
return ctf_errno (fp);
|
||||||
|
|
||||||
|
if (!isroot)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (ctf_insert_type_decl_tag (fp, id, name, kind) < 0)
|
||||||
|
return ctf_errno (fp);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case CTF_K_FORWARD:
|
case CTF_K_FORWARD:
|
||||||
{
|
{
|
||||||
ctf_dynhash_t *h = ctf_name_table (fp, tp->ctt_type);
|
int kflag = CTF_INFO_KFLAG (tp->ctt_info);
|
||||||
|
ctf_dynhash_t *h = ctf_name_table (fp, kflag == 1
|
||||||
|
? CTF_K_UNION : CTF_K_STRUCT);
|
||||||
|
|
||||||
if (!isroot)
|
if (!isroot)
|
||||||
break;
|
break;
|
||||||
@@ -927,7 +1078,7 @@ init_static_types_names_internal (ctf_dict_t *fp, ctf_header_t *cth,
|
|||||||
if (ctf_dynhash_lookup_type (h, name) == 0)
|
if (ctf_dynhash_lookup_type (h, name) == 0)
|
||||||
{
|
{
|
||||||
err = ctf_dynhash_insert_type (fp, h, ctf_index_to_type (fp, id),
|
err = ctf_dynhash_insert_type (fp, h, ctf_index_to_type (fp, id),
|
||||||
tp->ctt_name);
|
suffix->ctt_name);
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
return err * -1;
|
return err * -1;
|
||||||
}
|
}
|
||||||
@@ -939,22 +1090,12 @@ init_static_types_names_internal (ctf_dict_t *fp, ctf_header_t *cth,
|
|||||||
store the index of the pointer type in fp->ctf_ptrtab[ index of
|
store the index of the pointer type in fp->ctf_ptrtab[ index of
|
||||||
referenced type ]. */
|
referenced type ]. */
|
||||||
|
|
||||||
if (ctf_type_ischild (fp, tp->ctt_type) == child
|
if (ctf_type_ischild (fp, suffix->ctt_type) == child
|
||||||
&& ctf_type_to_index (fp, tp->ctt_type) <= fp->ctf_typemax)
|
&& ctf_type_to_index (fp, suffix->ctt_type) <= fp->ctf_typemax)
|
||||||
fp->ctf_ptrtab[ctf_type_to_index (fp, tp->ctt_type)] = id;
|
fp->ctf_ptrtab[ctf_type_to_index (fp, suffix->ctt_type)] = id;
|
||||||
/*FALLTHRU*/
|
|
||||||
|
|
||||||
case CTF_K_VOLATILE:
|
|
||||||
case CTF_K_CONST:
|
|
||||||
case CTF_K_RESTRICT:
|
|
||||||
if (!isroot)
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
err = ctf_dynhash_insert_type (fp, fp->ctf_names,
|
|
||||||
ctf_index_to_type (fp, id), 0);
|
|
||||||
if (err != 0)
|
|
||||||
return err * -1;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
ctf_err_warn (fp, 0, ECTF_CORRUPT,
|
ctf_err_warn (fp, 0, ECTF_CORRUPT,
|
||||||
_("init_static_types(): unhandled CTF kind: %x"), kind);
|
_("init_static_types(): unhandled CTF kind: %x"), kind);
|
||||||
@@ -962,10 +1103,12 @@ init_static_types_names_internal (ctf_dict_t *fp, ctf_header_t *cth,
|
|||||||
}
|
}
|
||||||
tp = (ctf_type_t *) ((uintptr_t) tp + increment + vbytes);
|
tp = (ctf_type_t *) ((uintptr_t) tp + increment + vbytes);
|
||||||
}
|
}
|
||||||
fp->ctf_typemax--;
|
assert (fp->ctf_typemax == id - 1);
|
||||||
assert (fp->ctf_typemax == typemax);
|
|
||||||
|
|
||||||
ctf_dprintf ("%u total types processed\n", fp->ctf_typemax);
|
ctf_dprintf ("%u total types processed\n", id - 1);
|
||||||
|
|
||||||
|
if ((err = init_void (fp) < 0))
|
||||||
|
return err;
|
||||||
|
|
||||||
/* In the third pass, we traverse the enums we spotted earlier and track all
|
/* In the third pass, we traverse the enums we spotted earlier and track all
|
||||||
the enumeration constants to aid in future detection of duplicates.
|
the enumeration constants to aid in future detection of duplicates.
|
||||||
@@ -974,6 +1117,9 @@ init_static_types_names_internal (ctf_dict_t *fp, ctf_header_t *cth,
|
|||||||
enum appears with a constant FOO, then later a type named FOO appears,
|
enum appears with a constant FOO, then later a type named FOO appears,
|
||||||
too late to spot the conflict by checking the enum's constants. */
|
too late to spot the conflict by checking the enum's constants. */
|
||||||
|
|
||||||
|
ctf_dprintf ("Extracting enumeration constants from %zu enums\n",
|
||||||
|
ctf_dynset_elements (all_enums));
|
||||||
|
|
||||||
while ((err = ctf_dynset_next (all_enums, &i, &k)) == 0)
|
while ((err = ctf_dynset_next (all_enums, &i, &k)) == 0)
|
||||||
{
|
{
|
||||||
ctf_id_t enum_id = (uintptr_t) k;
|
ctf_id_t enum_id = (uintptr_t) k;
|
||||||
@@ -998,20 +1144,94 @@ init_static_types_names_internal (ctf_dict_t *fp, ctf_header_t *cth,
|
|||||||
if (err != ECTF_NEXT_END)
|
if (err != ECTF_NEXT_END)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
/* In the final pass, we traverse all datasecs and remember the variables in
|
||||||
|
each, so we can rapidly map from variable back to datasec. */
|
||||||
|
|
||||||
|
ctf_dprintf ("Getting variable datasec membership\n");
|
||||||
|
|
||||||
|
while ((type = ctf_type_kind_next (fp, &i, CTF_K_DATASEC)) != CTF_ERR)
|
||||||
|
{
|
||||||
|
ctf_next_t *i_sec = NULL;
|
||||||
|
ctf_id_t var_type;
|
||||||
|
|
||||||
|
while ((var_type = ctf_datasec_var_next (fp, type, &i_sec, NULL, NULL))
|
||||||
|
!= CTF_ERR)
|
||||||
|
{
|
||||||
|
err = ctf_dynhash_insert (fp->ctf_var_datasecs,
|
||||||
|
(void *) (ptrdiff_t) var_type,
|
||||||
|
(void *) (ptrdiff_t) type);
|
||||||
|
if (err != 0)
|
||||||
|
return err * -1;
|
||||||
|
}
|
||||||
|
if (ctf_errno (fp) != ECTF_NEXT_END)
|
||||||
|
{
|
||||||
|
ctf_next_destroy (i);
|
||||||
|
return ctf_errno (fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ctf_errno (fp) != ECTF_NEXT_END)
|
||||||
|
return ctf_errno (fp);
|
||||||
|
|
||||||
ctf_dprintf ("%zu enum names hashed\n",
|
ctf_dprintf ("%zu enum names hashed\n",
|
||||||
ctf_dynhash_elements (fp->ctf_enums));
|
ctf_dynhash_elements (fp->ctf_enums));
|
||||||
ctf_dprintf ("%zu conflicting enumerators identified\n",
|
ctf_dprintf ("%zu conflicting enumerators identified\n",
|
||||||
ctf_dynset_elements (fp->ctf_conflicting_enums));
|
ctf_dynset_elements (fp->ctf_conflicting_enums));
|
||||||
ctf_dprintf ("%zu struct names hashed (%d long)\n",
|
ctf_dprintf ("%zu struct names hashed\n",
|
||||||
ctf_dynhash_elements (fp->ctf_structs), nlstructs);
|
ctf_dynhash_elements (fp->ctf_structs));
|
||||||
ctf_dprintf ("%zu union names hashed (%d long)\n",
|
ctf_dprintf ("%zu union names hashed\n",
|
||||||
ctf_dynhash_elements (fp->ctf_unions), nlunions);
|
ctf_dynhash_elements (fp->ctf_unions));
|
||||||
ctf_dprintf ("%zu base type names and identifiers hashed\n",
|
ctf_dprintf ("%zu base type names and identifiers hashed\n",
|
||||||
ctf_dynhash_elements (fp->ctf_names));
|
ctf_dynhash_elements (fp->ctf_names));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Prepare the void type. If present, index 0 is pointed at it: otherwise, we
|
||||||
|
make one in the ctf_void_type member and point index 0 at that. Because this
|
||||||
|
is index 0, it is not written out by serialization (which always starts at
|
||||||
|
index 1): because it is type 0, it is the type expected by BTF consumers:
|
||||||
|
because it is a real, queryable type, CTF consumers will get a proper type
|
||||||
|
back that they can query the properties of.
|
||||||
|
|
||||||
|
As an initialization function, this returns a positive error code, or
|
||||||
|
zero. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
init_void (ctf_dict_t *fp)
|
||||||
|
{
|
||||||
|
ctf_id_t void_type;
|
||||||
|
ctf_type_t *void_tp;
|
||||||
|
|
||||||
|
void_type = ctf_dynhash_lookup_type (ctf_name_table (fp, CTF_K_INTEGER), "void");
|
||||||
|
|
||||||
|
if (void_type == 0)
|
||||||
|
{
|
||||||
|
uint32_t *vlen;
|
||||||
|
|
||||||
|
if ((void_tp = calloc (1, sizeof (ctf_type_t) + sizeof (uint32_t))) == NULL)
|
||||||
|
return ENOMEM;
|
||||||
|
vlen = (uint32_t *) (void_tp + 1);
|
||||||
|
|
||||||
|
void_tp->ctt_name = ctf_str_add (fp, "void");
|
||||||
|
void_tp->ctt_info = CTF_TYPE_INFO (CTF_K_INTEGER, 0, 0);
|
||||||
|
void_tp->ctt_size = 4; /* (bytes) */
|
||||||
|
*vlen = CTF_INT_DATA (CTF_INT_SIGNED, 0, 0);
|
||||||
|
|
||||||
|
fp->ctf_void_type = void_tp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ctf_dict_t *tmp = fp;
|
||||||
|
|
||||||
|
void_tp = (ctf_type_t *) ctf_lookup_by_id (&tmp, void_type, NULL);
|
||||||
|
assert (void_tp != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
fp->ctf_txlate[0] = void_tp;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Endianness-flipping routines.
|
/* Endianness-flipping routines.
|
||||||
|
|
||||||
We flip everything, mindlessly, even 1-byte entities, so that future
|
We flip everything, mindlessly, even 1-byte entities, so that future
|
||||||
@@ -1371,12 +1591,15 @@ void ctf_set_ctl_hashes (ctf_dict_t *fp)
|
|||||||
fp->ctf_lookups[2].ctl_prefix = "enum";
|
fp->ctf_lookups[2].ctl_prefix = "enum";
|
||||||
fp->ctf_lookups[2].ctl_len = strlen (fp->ctf_lookups[2].ctl_prefix);
|
fp->ctf_lookups[2].ctl_len = strlen (fp->ctf_lookups[2].ctl_prefix);
|
||||||
fp->ctf_lookups[2].ctl_hash = fp->ctf_enums;
|
fp->ctf_lookups[2].ctl_hash = fp->ctf_enums;
|
||||||
fp->ctf_lookups[3].ctl_prefix = _CTF_NULLSTR;
|
fp->ctf_lookups[3].ctl_prefix = "datasec";
|
||||||
fp->ctf_lookups[3].ctl_len = strlen (fp->ctf_lookups[3].ctl_prefix);
|
fp->ctf_lookups[3].ctl_len = strlen (fp->ctf_lookups[3].ctl_prefix);
|
||||||
fp->ctf_lookups[3].ctl_hash = fp->ctf_names;
|
fp->ctf_lookups[3].ctl_hash = fp->ctf_datasecs;
|
||||||
fp->ctf_lookups[4].ctl_prefix = NULL;
|
fp->ctf_lookups[4].ctl_prefix = _CTF_NULLSTR;
|
||||||
fp->ctf_lookups[4].ctl_len = 0;
|
fp->ctf_lookups[4].ctl_len = strlen (fp->ctf_lookups[4].ctl_prefix);
|
||||||
fp->ctf_lookups[4].ctl_hash = NULL;
|
fp->ctf_lookups[4].ctl_hash = fp->ctf_names;
|
||||||
|
fp->ctf_lookups[5].ctl_prefix = NULL;
|
||||||
|
fp->ctf_lookups[5].ctl_len = 0;
|
||||||
|
fp->ctf_lookups[5].ctl_hash = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open a CTF file, mocking up a suitable ctf_sect. */
|
/* Open a CTF file, mocking up a suitable ctf_sect. */
|
||||||
@@ -2149,6 +2372,8 @@ ctf_dict_close (ctf_dict_t *fp)
|
|||||||
ctf_dynhash_destroy (fp->ctf_structs);
|
ctf_dynhash_destroy (fp->ctf_structs);
|
||||||
ctf_dynhash_destroy (fp->ctf_unions);
|
ctf_dynhash_destroy (fp->ctf_unions);
|
||||||
ctf_dynhash_destroy (fp->ctf_enums);
|
ctf_dynhash_destroy (fp->ctf_enums);
|
||||||
|
ctf_dynhash_destroy (fp->ctf_datasecs);
|
||||||
|
ctf_dynhash_destroy (fp->ctf_tags);
|
||||||
ctf_dynhash_destroy (fp->ctf_names);
|
ctf_dynhash_destroy (fp->ctf_names);
|
||||||
|
|
||||||
for (dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL; dvd = nvd)
|
for (dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL; dvd = nvd)
|
||||||
@@ -2157,6 +2382,7 @@ ctf_dict_close (ctf_dict_t *fp)
|
|||||||
ctf_dvd_delete (fp, dvd);
|
ctf_dvd_delete (fp, dvd);
|
||||||
}
|
}
|
||||||
ctf_dynhash_destroy (fp->ctf_dvhash);
|
ctf_dynhash_destroy (fp->ctf_dvhash);
|
||||||
|
ctf_dynhash_destroy (fp->ctf_var_datasecs);
|
||||||
|
|
||||||
ctf_dynhash_destroy (fp->ctf_symhash_func);
|
ctf_dynhash_destroy (fp->ctf_symhash_func);
|
||||||
ctf_dynhash_destroy (fp->ctf_symhash_objt);
|
ctf_dynhash_destroy (fp->ctf_symhash_objt);
|
||||||
@@ -2217,6 +2443,7 @@ ctf_dict_close (ctf_dict_t *fp)
|
|||||||
free (err);
|
free (err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free (fp->ctf_void_type);
|
||||||
free (fp->ctf_sxlate);
|
free (fp->ctf_sxlate);
|
||||||
free (fp->ctf_txlate);
|
free (fp->ctf_txlate);
|
||||||
free (fp->ctf_ptrtab);
|
free (fp->ctf_ptrtab);
|
||||||
@@ -2439,7 +2666,8 @@ ctf_import_internal (ctf_dict_t *fp, ctf_dict_t *pfp, int unreffed)
|
|||||||
fp->ctf_flags |= LCTF_CHILD;
|
fp->ctf_flags |= LCTF_CHILD;
|
||||||
fp->ctf_flags &= ~LCTF_NO_STR;
|
fp->ctf_flags &= ~LCTF_NO_STR;
|
||||||
|
|
||||||
if (no_strings && (err = init_static_types_names (fp, fp->ctf_header)) < 0)
|
if (no_strings && (err = init_static_types_names (fp, fp->ctf_header,
|
||||||
|
fp->ctf_opened_btf) < 0))
|
||||||
{
|
{
|
||||||
/* Undo everything other than cache flushing. */
|
/* Undo everything other than cache flushing. */
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user