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:
Nick Alcock
2025-04-24 14:58:50 +01:00
parent f7d05ab342
commit ad13b7d44f
5 changed files with 373 additions and 115 deletions

View File

@@ -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. */