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:
@@ -560,7 +560,7 @@ ctf_set_base (ctf_dict_t *fp, const ctf_header_t *hp, unsigned char *base)
|
||||
}
|
||||
|
||||
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).
|
||||
|
||||
@@ -591,50 +591,105 @@ init_static_types (ctf_dict_t *fp, ctf_header_t *cth, int is_btf)
|
||||
fp->ctf_provtypemax = (uint32_t) -1;
|
||||
|
||||
/* 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 0
|
||||
int err;
|
||||
|
||||
if ((err = upgrade_types (fp, cth)) != 0)
|
||||
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);
|
||||
tend = (ctf_type_t *) (fp->ctf_buf + cth->cth_stroff);
|
||||
tbuf = (ctf_type_t *) (fp->ctf_buf + cth->btf.bth_type_off);
|
||||
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
|
||||
through part of it: but only the first is guaranteed to happen at this
|
||||
stage. The second and third passes require working string lookup, so in
|
||||
child dicts can only happen at ctf_import time.
|
||||
/* We make two passes through the entire type section, and more passes through
|
||||
parts of it: but only the first is guaranteed to happen at this stage. The
|
||||
later passes require working string lookup, so in child dicts can only
|
||||
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
|
||||
identifier (like enumerators) and the total number of types. */
|
||||
|
||||
for (tp = tbuf; tp < tend; typemax++)
|
||||
{
|
||||
unsigned short kind = LCTF_INFO_KIND (fp, tp->ctt_info);
|
||||
unsigned long vlen = LCTF_INFO_VLEN (fp, tp->ctt_info);
|
||||
unsigned short kind = LCTF_INFO_UNPREFIXED_KIND (fp, tp->ctt_info);
|
||||
size_t vlen = LCTF_VLEN (fp, tp);
|
||||
int nonroot = 0;
|
||||
ssize_t size, increment, vbytes;
|
||||
const ctf_type_t *suffix = tp;
|
||||
|
||||
(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)
|
||||
return ECTF_CORRUPT;
|
||||
|
||||
/* For forward declarations, ctt_type is the CTF_K_* kind for the tag,
|
||||
so bump that population count too. */
|
||||
if (kind == CTF_K_FORWARD)
|
||||
pop[tp->ctt_type]++;
|
||||
if (!nonroot)
|
||||
{
|
||||
/* 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 (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);
|
||||
pop[kind]++;
|
||||
|
||||
if (kind == CTF_K_ENUM)
|
||||
pop_enumerators += vlen;
|
||||
}
|
||||
|
||||
if (child)
|
||||
@@ -666,11 +721,24 @@ init_static_types (ctf_dict_t *fp, ctf_header_t *cth, int is_btf)
|
||||
NULL, NULL, NULL)) == NULL)
|
||||
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
|
||||
= ctf_dynhash_create_sized (pop[CTF_K_UNKNOWN] +
|
||||
pop[CTF_K_INTEGER] +
|
||||
pop[CTF_K_FLOAT] +
|
||||
pop[CTF_K_FUNCTION] +
|
||||
pop[CTF_K_FUNC_LINKAGE] +
|
||||
pop[CTF_K_TYPEDEF] +
|
||||
pop_enumerators,
|
||||
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)
|
||||
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
|
||||
= ctf_dynset_create (htab_hash_string, htab_eq_string, NULL)) == NULL)
|
||||
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)
|
||||
return ENOMEM; /* Memory allocation failed. */
|
||||
|
||||
/* UPTODO: BTF is like v4 here: no string lookups in children, which blocks
|
||||
almost all operations until after ctf_import. */
|
||||
if (child && cth->cth_parent_strlen != 0)
|
||||
if (child || cth->cth_parent_strlen != 0)
|
||||
{
|
||||
fp->ctf_flags |= LCTF_NO_STR;
|
||||
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);
|
||||
|
||||
return init_static_types_names (fp, cth);
|
||||
return init_static_types_names (fp, cth, is_btf);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/* A wrapper to simplify memory allocation. */
|
||||
|
||||
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;
|
||||
int err;
|
||||
@@ -727,41 +798,43 @@ init_static_types_names (ctf_dict_t *fp, ctf_header_t *cth)
|
||||
NULL)) == NULL)
|
||||
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);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Initialize the parts of the CTF dict whose initialization depends on name
|
||||
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
|
||||
is truncated at the start.
|
||||
static int
|
||||
init_void (ctf_dict_t *fp);
|
||||
|
||||
/* 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
|
||||
set the ctf_errno, but instead *returns* the error code. */
|
||||
set the ctf_errno, but instead returns a positive error code. */
|
||||
|
||||
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)
|
||||
{
|
||||
const ctf_type_t *tbuf;
|
||||
const ctf_type_t *tend;
|
||||
ctf_type_t *tbuf, *tend, *tp;
|
||||
ctf_type_t **xp;
|
||||
|
||||
const ctf_type_t *tp;
|
||||
uint32_t id;
|
||||
uint32_t *xp;
|
||||
|
||||
unsigned long typemax = fp->ctf_typemax;
|
||||
ctf_id_t type;
|
||||
|
||||
ctf_next_t *i = NULL;
|
||||
void *k;
|
||||
int err;
|
||||
|
||||
int child = cth->cth_parname != 0;
|
||||
int nlstructs = 0, nlunions = 0;
|
||||
/* See init_static_types. */
|
||||
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);
|
||||
tend = (ctf_type_t *) (fp->ctf_buf + cth->cth_stroff);
|
||||
tbuf = (ctf_type_t *) (fp->ctf_buf + cth->btf.bth_type_off);
|
||||
tend = (ctf_type_t *) ((uintptr_t) tbuf + cth->btf.bth_type_len);
|
||||
|
||||
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
|
||||
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,
|
||||
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++)
|
||||
for (id = 1, tp = tbuf; tp < tend; xp++, id++)
|
||||
{
|
||||
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 long vlen = LCTF_INFO_VLEN (fp, tp->ctt_info);
|
||||
size_t vlen = LCTF_VLEN (fp, tp);
|
||||
ssize_t size, increment, vbytes;
|
||||
|
||||
const ctf_type_t *suffix = tp;
|
||||
const char *name;
|
||||
|
||||
(void) ctf_get_ctt_size (fp, tp, &size, &increment);
|
||||
name = ctf_strptr (fp, tp->ctt_name);
|
||||
/* Cannot fail: shielded by call in loop above. */
|
||||
vbytes = LCTF_VBYTES (fp, kind, size, vlen);
|
||||
/* Prefixed type: pull off the prefixes (for most purposes). (We already
|
||||
know the prefixes cannot overflow.) */
|
||||
|
||||
*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)
|
||||
{
|
||||
@@ -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
|
||||
bit-width wider than the existing one, since the native type
|
||||
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)
|
||||
|| 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,
|
||||
ctf_index_to_type (fp, id),
|
||||
tp->ctt_name);
|
||||
suffix->ctt_name);
|
||||
if (err != 0)
|
||||
return err * -1;
|
||||
}
|
||||
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
|
||||
hashtables. */
|
||||
case CTF_K_ARRAY:
|
||||
case CTF_K_SLICE:
|
||||
case CTF_K_VOLATILE:
|
||||
case CTF_K_CONST:
|
||||
case CTF_K_RESTRICT:
|
||||
case CTF_K_FUNCTION:
|
||||
break;
|
||||
|
||||
case CTF_K_FUNCTION:
|
||||
case CTF_K_FUNC_LINKAGE:
|
||||
if (!isroot)
|
||||
break;
|
||||
|
||||
err = ctf_dynhash_insert_type (fp, fp->ctf_names,
|
||||
ctf_index_to_type (fp, id),
|
||||
tp->ctt_name);
|
||||
suffix->ctt_name);
|
||||
if (err != 0)
|
||||
return err * -1;
|
||||
break;
|
||||
|
||||
case CTF_K_STRUCT:
|
||||
if (size >= CTF_LSTRUCT_THRESH)
|
||||
nlstructs++;
|
||||
|
||||
if (!isroot)
|
||||
break;
|
||||
|
||||
err = ctf_dynhash_insert_type (fp, fp->ctf_structs,
|
||||
ctf_index_to_type (fp, id),
|
||||
tp->ctt_name);
|
||||
suffix->ctt_name);
|
||||
|
||||
if (err != 0)
|
||||
return err * -1;
|
||||
@@ -869,38 +971,45 @@ init_static_types_names_internal (ctf_dict_t *fp, ctf_header_t *cth,
|
||||
break;
|
||||
|
||||
case CTF_K_UNION:
|
||||
if (size >= CTF_LSTRUCT_THRESH)
|
||||
nlunions++;
|
||||
|
||||
if (!isroot)
|
||||
break;
|
||||
|
||||
err = ctf_dynhash_insert_type (fp, fp->ctf_unions,
|
||||
ctf_index_to_type (fp, id),
|
||||
tp->ctt_name);
|
||||
suffix->ctt_name);
|
||||
|
||||
if (err != 0)
|
||||
return err * -1;
|
||||
break;
|
||||
|
||||
case CTF_K_ENUM:
|
||||
case CTF_K_ENUM64:
|
||||
{
|
||||
if (!isroot)
|
||||
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,
|
||||
ctf_index_to_type (fp, id),
|
||||
tp->ctt_name);
|
||||
suffix->ctt_name);
|
||||
|
||||
if (err != 0)
|
||||
return err * -1;
|
||||
|
||||
/* Remember all enums for later rescanning. */
|
||||
/* Remember all non-forward enums for later rescanning. */
|
||||
|
||||
err = ctf_dynset_insert (all_enums, (void *) (ptrdiff_t)
|
||||
ctf_index_to_type (fp, id));
|
||||
if (err != 0)
|
||||
return err * -1;
|
||||
if (vlen != 0)
|
||||
{
|
||||
err = ctf_dynset_insert (all_enums, (void *) (ptrdiff_t)
|
||||
ctf_index_to_type (fp, id));
|
||||
if (err != 0)
|
||||
return err * -1;
|
||||
}
|
||||
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,
|
||||
ctf_index_to_type (fp, id),
|
||||
tp->ctt_name);
|
||||
suffix->ctt_name);
|
||||
if (err != 0)
|
||||
return err * -1;
|
||||
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:
|
||||
{
|
||||
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)
|
||||
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)
|
||||
{
|
||||
err = ctf_dynhash_insert_type (fp, h, ctf_index_to_type (fp, id),
|
||||
tp->ctt_name);
|
||||
suffix->ctt_name);
|
||||
if (err != 0)
|
||||
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
|
||||
referenced type ]. */
|
||||
|
||||
if (ctf_type_ischild (fp, tp->ctt_type) == child
|
||||
&& ctf_type_to_index (fp, tp->ctt_type) <= fp->ctf_typemax)
|
||||
fp->ctf_ptrtab[ctf_type_to_index (fp, tp->ctt_type)] = id;
|
||||
/*FALLTHRU*/
|
||||
if (ctf_type_ischild (fp, suffix->ctt_type) == child
|
||||
&& ctf_type_to_index (fp, suffix->ctt_type) <= fp->ctf_typemax)
|
||||
fp->ctf_ptrtab[ctf_type_to_index (fp, suffix->ctt_type)] = id;
|
||||
|
||||
case CTF_K_VOLATILE:
|
||||
case CTF_K_CONST:
|
||||
case CTF_K_RESTRICT:
|
||||
if (!isroot)
|
||||
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:
|
||||
ctf_err_warn (fp, 0, ECTF_CORRUPT,
|
||||
_("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);
|
||||
}
|
||||
fp->ctf_typemax--;
|
||||
assert (fp->ctf_typemax == typemax);
|
||||
assert (fp->ctf_typemax == id - 1);
|
||||
|
||||
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
|
||||
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,
|
||||
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)
|
||||
{
|
||||
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)
|
||||
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_dynhash_elements (fp->ctf_enums));
|
||||
ctf_dprintf ("%zu conflicting enumerators identified\n",
|
||||
ctf_dynset_elements (fp->ctf_conflicting_enums));
|
||||
ctf_dprintf ("%zu struct names hashed (%d long)\n",
|
||||
ctf_dynhash_elements (fp->ctf_structs), nlstructs);
|
||||
ctf_dprintf ("%zu union names hashed (%d long)\n",
|
||||
ctf_dynhash_elements (fp->ctf_unions), nlunions);
|
||||
ctf_dprintf ("%zu struct names hashed\n",
|
||||
ctf_dynhash_elements (fp->ctf_structs));
|
||||
ctf_dprintf ("%zu union names hashed\n",
|
||||
ctf_dynhash_elements (fp->ctf_unions));
|
||||
ctf_dprintf ("%zu base type names and identifiers hashed\n",
|
||||
ctf_dynhash_elements (fp->ctf_names));
|
||||
|
||||
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.
|
||||
|
||||
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_len = strlen (fp->ctf_lookups[2].ctl_prefix);
|
||||
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_hash = fp->ctf_names;
|
||||
fp->ctf_lookups[4].ctl_prefix = NULL;
|
||||
fp->ctf_lookups[4].ctl_len = 0;
|
||||
fp->ctf_lookups[4].ctl_hash = NULL;
|
||||
fp->ctf_lookups[3].ctl_hash = fp->ctf_datasecs;
|
||||
fp->ctf_lookups[4].ctl_prefix = _CTF_NULLSTR;
|
||||
fp->ctf_lookups[4].ctl_len = strlen (fp->ctf_lookups[4].ctl_prefix);
|
||||
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. */
|
||||
@@ -2149,6 +2372,8 @@ ctf_dict_close (ctf_dict_t *fp)
|
||||
ctf_dynhash_destroy (fp->ctf_structs);
|
||||
ctf_dynhash_destroy (fp->ctf_unions);
|
||||
ctf_dynhash_destroy (fp->ctf_enums);
|
||||
ctf_dynhash_destroy (fp->ctf_datasecs);
|
||||
ctf_dynhash_destroy (fp->ctf_tags);
|
||||
ctf_dynhash_destroy (fp->ctf_names);
|
||||
|
||||
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_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_objt);
|
||||
@@ -2217,6 +2443,7 @@ ctf_dict_close (ctf_dict_t *fp)
|
||||
free (err);
|
||||
}
|
||||
|
||||
free (fp->ctf_void_type);
|
||||
free (fp->ctf_sxlate);
|
||||
free (fp->ctf_txlate);
|
||||
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_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. */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user