libctf: remove static/dynamic name lookup distinction

libctf internally maintains a set of hash tables for type name lookups,
one for each valid C type namespace (struct, union, enum, and everything
else).

Or, rather, it maintains *two* sets of hash tables: one, a ctf_hash *,
is meant for lookups in ctf_(buf)open()ed dicts with fixed content; the
other, a ctf_dynhash *, is meant for lookups in ctf_create()d dicts.

This distinction was somewhat valuable in the far pre-binutils past when
two different hashtable implementations were used (one expanding, the
other fixed-size), but those days are long gone: the hash table
implementations are almost identical, both wrappers around the libiberty
hashtab. The ctf_dynhash has many more capabilities than the ctf_hash
(iteration, deletion, etc etc) and has no downsides other than starting
at a fixed, arbitrary small size.

That limitation is easy to lift (via a new ctf_dynhash_create_sized()),
following which we can throw away nearly all the ctf_hash
implementation, and all the code to choose between readable and writable
hashtabs; the few convenience functions that are still useful (for
insertion of name -> type mappings) can also be generalized a bit so
that the extra string verification they do is potentially available to
other string lookups as well.

(libctf still has two hashtable implementations, ctf_dynhash, above,
and ctf_dynset, which is a key-only hashtab that can avoid a great many
malloc()s, used for high-volume applications in the deduplicator.)

libctf/

	* ctf-create.c (ctf_create): Eliminate ctn_writable.
	(ctf_dtd_insert): Likewise.
	(ctf_dtd_delete): Likewise.
	(ctf_rollback): Likewise.
	(ctf_name_table): Eliminate ctf_names_t.
	* ctf-hash.c (ctf_dynhash_create): Comment update.
        Reimplement in terms of...
	(ctf_dynhash_create_sized): ... this new function.
	(ctf_hash_create): Remove.
	(ctf_hash_size): Remove.
	(ctf_hash_define_type): Remove.
	(ctf_hash_destroy): Remove.
	(ctf_hash_lookup_type): Rename to...
	(ctf_dynhash_lookup_type): ... this.
	(ctf_hash_insert_type): Rename to...
	(ctf_dynhash_insert_type): ... this, moving validation to...
	* ctf-string.c (ctf_strptr_validate): ... this new function.
	* ctf-impl.h (struct ctf_names): Extirpate.
	(struct ctf_lookup.ctl_hash): Now a ctf_dynhash_t.
	(struct ctf_dict): All ctf_names_t fields are now ctf_dynhash_t.
	(ctf_name_table): Now returns a ctf_dynhash_t.
	(ctf_lookup_by_rawhash): Remove.
	(ctf_hash_create): Likewise.
	(ctf_hash_insert_type): Likewise.
	(ctf_hash_define_type): Likewise.
	(ctf_hash_lookup_type): Likewise.
	(ctf_hash_size): Likewise.
	(ctf_hash_destroy): Likewise.
	(ctf_dynhash_create_sized): New.
	(ctf_dynhash_insert_type): New.
	(ctf_dynhash_lookup_type): New.
	(ctf_strptr_validate): New.
	* ctf-lookup.c (ctf_lookup_by_name_internal): Adapt.
	* ctf-open.c (init_types): Adapt.
	(ctf_set_ctl_hashes): Adapt.
	(ctf_dict_close): Adapt.
	* ctf-serialize.c (ctf_serialize): Adapt.
	* ctf-types.c (ctf_lookup_by_rawhash): Remove.
This commit is contained in:
Nick Alcock
2023-12-18 17:47:48 +00:00
parent ca01922784
commit 54a0219150
8 changed files with 157 additions and 201 deletions

View File

@@ -154,10 +154,10 @@ ctf_create (int *errp)
if ((fp = ctf_bufopen_internal (&cts, NULL, NULL, NULL, 1, errp)) == NULL) if ((fp = ctf_bufopen_internal (&cts, NULL, NULL, NULL, 1, errp)) == NULL)
goto err_dv; goto err_dv;
fp->ctf_structs.ctn_writable = structs; fp->ctf_structs = structs;
fp->ctf_unions.ctn_writable = unions; fp->ctf_unions = unions;
fp->ctf_enums.ctn_writable = enums; fp->ctf_enums = enums;
fp->ctf_names.ctn_writable = names; fp->ctf_names = names;
fp->ctf_objthash = objthash; fp->ctf_objthash = objthash;
fp->ctf_funchash = funchash; fp->ctf_funchash = funchash;
fp->ctf_dthash = dthash; fp->ctf_dthash = dthash;
@@ -203,19 +203,19 @@ ctf_update (ctf_dict_t *fp)
return 0; return 0;
} }
ctf_names_t * ctf_dynhash_t *
ctf_name_table (ctf_dict_t *fp, int kind) ctf_name_table (ctf_dict_t *fp, int kind)
{ {
switch (kind) switch (kind)
{ {
case CTF_K_STRUCT: case CTF_K_STRUCT:
return &fp->ctf_structs; return fp->ctf_structs;
case CTF_K_UNION: case CTF_K_UNION:
return &fp->ctf_unions; return fp->ctf_unions;
case CTF_K_ENUM: case CTF_K_ENUM:
return &fp->ctf_enums; return fp->ctf_enums;
default: default:
return &fp->ctf_names; return fp->ctf_names;
} }
} }
@@ -230,7 +230,7 @@ ctf_dtd_insert (ctf_dict_t *fp, ctf_dtdef_t *dtd, int flag, int kind)
if (flag == CTF_ADD_ROOT && dtd->dtd_data.ctt_name if (flag == CTF_ADD_ROOT && dtd->dtd_data.ctt_name
&& (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL) && (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL)
{ {
if (ctf_dynhash_insert (ctf_name_table (fp, kind)->ctn_writable, if (ctf_dynhash_insert (ctf_name_table (fp, kind),
(char *) name, (void *) (uintptr_t) (char *) name, (void *) (uintptr_t)
dtd->dtd_type) < 0) dtd->dtd_type) < 0)
{ {
@@ -287,8 +287,7 @@ ctf_dtd_delete (ctf_dict_t *fp, ctf_dtdef_t *dtd)
&& (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL && (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL
&& LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info)) && LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info))
{ {
ctf_dynhash_remove (ctf_name_table (fp, name_kind)->ctn_writable, ctf_dynhash_remove (ctf_name_table (fp, name_kind), name);
name);
ctf_str_remove_ref (fp, name, &dtd->dtd_data.ctt_name); ctf_str_remove_ref (fp, name, &dtd->dtd_data.ctt_name);
} }
@@ -410,8 +409,7 @@ ctf_rollback (ctf_dict_t *fp, ctf_snapshot_id_t id)
&& (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL && (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL
&& LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info)) && LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info))
{ {
ctf_dynhash_remove (ctf_name_table (fp, kind)->ctn_writable, ctf_dynhash_remove (ctf_name_table (fp, kind), name);
name);
ctf_str_remove_ref (fp, name, &dtd->dtd_data.ctt_name); ctf_str_remove_ref (fp, name, &dtd->dtd_data.ctt_name);
} }

View File

@@ -22,25 +22,22 @@
#include "libiberty.h" #include "libiberty.h"
#include "hashtab.h" #include "hashtab.h"
/* We have three hashtable implementations: /* We have two hashtable implementations:
- ctf_hash_* is an interface to a fixed-size hash from const char * ->
ctf_id_t with number of elements specified at creation time, that should
support addition of items but need not support removal.
- ctf_dynhash_* is an interface to a dynamically-expanding hash with - ctf_dynhash_* is an interface to a dynamically-expanding hash with
unknown size that should support addition of large numbers of items, and unknown size that should support addition of large numbers of items,
removal as well, and is used only at type-insertion time and during and removal as well, and is used only at type-insertion time and during
linking. linking. It can be constructed with an expected initial number of
elements, but need not be.
- ctf_dynset_* is an interface to a dynamically-expanding hash that contains - ctf_dynset_* is an interface to a dynamically-expanding hash that contains
only keys: no values. only keys: no values.
These can be implemented by the same underlying hashmap if you wish. */ These can be implemented by the same underlying hashmap if you wish. */
/* The helem is used for general key/value mappings in both the ctf_hash and /* The helem is used for general key/value mappings in the ctf_dynhash: the
ctf_dynhash: the owner may not have space allocated for it, and will be owner may not have space allocated for it, and will be garbage (not
garbage (not NULL!) in that case. */ NULL!) in that case. */
typedef struct ctf_helem typedef struct ctf_helem
{ {
@@ -157,8 +154,9 @@ ctf_dynhash_item_free (void *item)
} }
ctf_dynhash_t * ctf_dynhash_t *
ctf_dynhash_create (ctf_hash_fun hash_fun, ctf_hash_eq_fun eq_fun, ctf_dynhash_create_sized (unsigned long nelems, ctf_hash_fun hash_fun,
ctf_hash_free_fun key_free, ctf_hash_free_fun value_free) ctf_hash_eq_fun eq_fun, ctf_hash_free_fun key_free,
ctf_hash_free_fun value_free)
{ {
ctf_dynhash_t *dynhash; ctf_dynhash_t *dynhash;
htab_del del = ctf_dynhash_item_free; htab_del del = ctf_dynhash_item_free;
@@ -173,8 +171,7 @@ ctf_dynhash_create (ctf_hash_fun hash_fun, ctf_hash_eq_fun eq_fun,
if (key_free == NULL && value_free == NULL) if (key_free == NULL && value_free == NULL)
del = free; del = free;
/* 7 is arbitrary and untested for now. */ if ((dynhash->htab = htab_create_alloc (nelems, (htab_hash) hash_fun, eq_fun,
if ((dynhash->htab = htab_create_alloc (7, (htab_hash) hash_fun, eq_fun,
del, xcalloc, free)) == NULL) del, xcalloc, free)) == NULL)
{ {
free (dynhash); free (dynhash);
@@ -190,6 +187,15 @@ ctf_dynhash_create (ctf_hash_fun hash_fun, ctf_hash_eq_fun eq_fun,
return dynhash; return dynhash;
} }
ctf_dynhash_t *
ctf_dynhash_create (ctf_hash_fun hash_fun, ctf_hash_eq_fun eq_fun,
ctf_hash_free_fun key_free, ctf_hash_free_fun value_free)
{
/* 7 is arbitrary and not benchmarked yet. */
return ctf_dynhash_create_sized (7, hash_fun, eq_fun, key_free, value_free);
}
static ctf_helem_t ** static ctf_helem_t **
ctf_hashtab_lookup (struct htab *htab, const void *key, enum insert_option insert) ctf_hashtab_lookup (struct htab *htab, const void *key, enum insert_option insert)
{ {
@@ -767,80 +773,38 @@ ctf_dynset_next (ctf_dynset_t *hp, ctf_next_t **it, void **key)
return ECTF_NEXT_END; return ECTF_NEXT_END;
} }
/* ctf_hash, used for fixed-size maps from const char * -> ctf_id_t without /* Helper functions for insertion/removal of types. */
removal. This is a straight cast of a hashtab. */
ctf_hash_t *
ctf_hash_create (unsigned long nelems, ctf_hash_fun hash_fun,
ctf_hash_eq_fun eq_fun)
{
return (ctf_hash_t *) htab_create_alloc (nelems, (htab_hash) hash_fun,
eq_fun, free, xcalloc, free);
}
uint32_t
ctf_hash_size (const ctf_hash_t *hp)
{
return htab_elements ((struct htab *) hp);
}
int int
ctf_hash_insert_type (ctf_hash_t *hp, ctf_dict_t *fp, uint32_t type, ctf_dynhash_insert_type (ctf_dict_t *fp, ctf_dynhash_t *hp, uint32_t type,
uint32_t name) uint32_t name)
{ {
const char *str = ctf_strraw (fp, name); const char *str;
int err;
if (type == 0) if (type == 0)
return EINVAL; return EINVAL;
if (str == NULL if ((str = ctf_strptr_validate (fp, name)) == NULL)
&& CTF_NAME_STID (name) == CTF_STRTAB_1 return ctf_errno (fp);
&& fp->ctf_syn_ext_strtab == NULL
&& fp->ctf_str[CTF_NAME_STID (name)].cts_strs == NULL)
return ECTF_STRTAB;
if (str == NULL)
return ECTF_BADNAME;
if (str[0] == '\0') if (str[0] == '\0')
return 0; /* Just ignore empty strings on behalf of caller. */ return 0; /* Just ignore empty strings on behalf of caller. */
if (ctf_hashtab_insert ((struct htab *) hp, (char *) str, if ((err = ctf_dynhash_insert (hp, (char *) str,
(void *) (ptrdiff_t) type, NULL, NULL) != NULL) (void *) (ptrdiff_t) type)) == 0)
return 0; return 0;
return errno;
}
/* if the key is already in the hash, override the previous definition with return err;
this new official definition. If the key is not present, then call
ctf_hash_insert_type and hash it in. */
int
ctf_hash_define_type (ctf_hash_t *hp, ctf_dict_t *fp, uint32_t type,
uint32_t name)
{
/* This matches the semantics of ctf_hash_insert_type in this
implementation anyway. */
return ctf_hash_insert_type (hp, fp, type, name);
} }
ctf_id_t ctf_id_t
ctf_hash_lookup_type (ctf_hash_t *hp, ctf_dict_t *fp __attribute__ ((__unused__)), ctf_dynhash_lookup_type (ctf_dynhash_t *hp, const char *key)
const char *key)
{ {
ctf_helem_t **slot; void *value;
slot = ctf_hashtab_lookup ((struct htab *) hp, key, NO_INSERT); if (ctf_dynhash_lookup_kv (hp, key, NULL, &value))
return (ctf_id_t) (uintptr_t) value;
if (slot)
return (ctf_id_t) (uintptr_t) ((*slot)->value);
return 0; return 0;
} }
void
ctf_hash_destroy (ctf_hash_t *hp)
{
if (hp != NULL)
htab_delete ((struct htab *) hp);
}

View File

@@ -123,17 +123,11 @@ typedef struct ctf_dmodel
size_t ctd_long; /* Size of long in bytes. */ size_t ctd_long; /* Size of long in bytes. */
} ctf_dmodel_t; } ctf_dmodel_t;
typedef struct ctf_names
{
ctf_hash_t *ctn_readonly; /* Hash table when readonly. */
ctf_dynhash_t *ctn_writable; /* Hash table when writable. */
} ctf_names_t;
typedef struct ctf_lookup typedef struct ctf_lookup
{ {
const char *ctl_prefix; /* String prefix for this lookup. */ const char *ctl_prefix; /* String prefix for this lookup. */
size_t ctl_len; /* Length of prefix string in bytes. */ size_t ctl_len; /* Length of prefix string in bytes. */
ctf_names_t *ctl_hash; /* Pointer to hash table for lookup. */ ctf_dynhash_t *ctl_hash; /* Pointer to hash table for lookup. */
} ctf_lookup_t; } ctf_lookup_t;
typedef struct ctf_dictops typedef struct ctf_dictops
@@ -382,10 +376,10 @@ struct ctf_dict
ctf_dynhash_t *ctf_syn_ext_strtab; /* Maps ext-strtab offsets to names. */ ctf_dynhash_t *ctf_syn_ext_strtab; /* Maps ext-strtab offsets to names. */
void *ctf_data_mmapped; /* CTF data we mmapped, to free later. */ void *ctf_data_mmapped; /* CTF data we mmapped, to free later. */
size_t ctf_data_mmapped_len; /* Length of CTF data we mmapped. */ size_t ctf_data_mmapped_len; /* Length of CTF data we mmapped. */
ctf_names_t ctf_structs; /* Hash table of struct types. */ ctf_dynhash_t *ctf_structs; /* Hash table of struct types. */
ctf_names_t ctf_unions; /* Hash table of union types. */ ctf_dynhash_t *ctf_unions; /* Hash table of union types. */
ctf_names_t ctf_enums; /* Hash table of enum types. */ ctf_dynhash_t *ctf_enums; /* Hash table of enum types. */
ctf_names_t ctf_names; /* Hash table of remaining type names. */ ctf_dynhash_t *ctf_names; /* Hash table of remaining type names. */
ctf_lookup_t ctf_lookups[5]; /* Pointers to nametabs for name lookup. */ ctf_lookup_t ctf_lookups[5]; /* Pointers to nametabs for name lookup. */
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_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. */
@@ -597,10 +591,9 @@ struct ctf_next
#define LCTF_DIRTY 0x0004 /* CTF dict has been modified. */ #define LCTF_DIRTY 0x0004 /* CTF dict has been modified. */
#define LCTF_LINKING 0x0008 /* CTF link is underway: respect ctf_link_flags. */ #define LCTF_LINKING 0x0008 /* CTF link is underway: respect ctf_link_flags. */
extern ctf_names_t *ctf_name_table (ctf_dict_t *, int); extern ctf_dynhash_t *ctf_name_table (ctf_dict_t *, int);
extern const ctf_type_t *ctf_lookup_by_id (ctf_dict_t **, ctf_id_t); extern const ctf_type_t *ctf_lookup_by_id (ctf_dict_t **, ctf_id_t);
extern ctf_id_t ctf_lookup_by_rawname (ctf_dict_t *, int, const char *); extern ctf_id_t ctf_lookup_by_rawname (ctf_dict_t *, int, const char *);
extern ctf_id_t ctf_lookup_by_rawhash (ctf_dict_t *, ctf_names_t *, const char *);
extern void ctf_set_ctl_hashes (ctf_dict_t *); extern void ctf_set_ctl_hashes (ctf_dict_t *);
extern int ctf_symtab_skippable (ctf_link_sym_t *sym); extern int ctf_symtab_skippable (ctf_link_sym_t *sym);
@@ -629,19 +622,19 @@ typedef int (*ctf_hash_iter_find_f) (void *key, void *value, void *arg);
typedef int (*ctf_hash_sort_f) (const ctf_next_hkv_t *, const ctf_next_hkv_t *, typedef int (*ctf_hash_sort_f) (const ctf_next_hkv_t *, const ctf_next_hkv_t *,
void *arg); void *arg);
extern ctf_hash_t *ctf_hash_create (unsigned long, ctf_hash_fun, ctf_hash_eq_fun);
extern int ctf_hash_insert_type (ctf_hash_t *, ctf_dict_t *, uint32_t, uint32_t);
extern int ctf_hash_define_type (ctf_hash_t *, ctf_dict_t *, uint32_t, uint32_t);
extern ctf_id_t ctf_hash_lookup_type (ctf_hash_t *, ctf_dict_t *, const char *);
extern uint32_t ctf_hash_size (const ctf_hash_t *);
extern void ctf_hash_destroy (ctf_hash_t *);
extern ctf_dynhash_t *ctf_dynhash_create (ctf_hash_fun, ctf_hash_eq_fun, extern ctf_dynhash_t *ctf_dynhash_create (ctf_hash_fun, ctf_hash_eq_fun,
ctf_hash_free_fun, ctf_hash_free_fun); ctf_hash_free_fun, ctf_hash_free_fun);
extern ctf_dynhash_t *ctf_dynhash_create_sized (unsigned long, ctf_hash_fun,
ctf_hash_eq_fun,
ctf_hash_free_fun,
ctf_hash_free_fun);
extern int ctf_dynhash_insert (ctf_dynhash_t *, void *, void *); extern int ctf_dynhash_insert (ctf_dynhash_t *, void *, void *);
extern void ctf_dynhash_remove (ctf_dynhash_t *, const void *); extern void ctf_dynhash_remove (ctf_dynhash_t *, const void *);
extern size_t ctf_dynhash_elements (ctf_dynhash_t *); extern size_t ctf_dynhash_elements (ctf_dynhash_t *);
extern void ctf_dynhash_empty (ctf_dynhash_t *); extern void ctf_dynhash_empty (ctf_dynhash_t *);
extern int ctf_dynhash_insert_type (ctf_dict_t *, ctf_dynhash_t *, uint32_t, uint32_t);
extern ctf_id_t ctf_dynhash_lookup_type (ctf_dynhash_t *, const char *);
extern void *ctf_dynhash_lookup (ctf_dynhash_t *, const void *); extern void *ctf_dynhash_lookup (ctf_dynhash_t *, const void *);
extern int ctf_dynhash_lookup_kv (ctf_dynhash_t *, const void *key, extern int ctf_dynhash_lookup_kv (ctf_dynhash_t *, const void *key,
const void **orig_key, void **value); const void **orig_key, void **value);
@@ -720,6 +713,7 @@ extern const char *ctf_strptr (ctf_dict_t *, uint32_t);
extern const char *ctf_strraw (ctf_dict_t *, uint32_t); extern const char *ctf_strraw (ctf_dict_t *, uint32_t);
extern const char *ctf_strraw_explicit (ctf_dict_t *, uint32_t, extern const char *ctf_strraw_explicit (ctf_dict_t *, uint32_t,
ctf_strs_t *); ctf_strs_t *);
extern const char *ctf_strptr_validate (ctf_dict_t *, uint32_t);
extern int ctf_str_create_atoms (ctf_dict_t *); extern int ctf_str_create_atoms (ctf_dict_t *);
extern void ctf_str_free_atoms (ctf_dict_t *); extern void ctf_str_free_atoms (ctf_dict_t *);
extern uint32_t ctf_str_add (ctf_dict_t *, const char *); extern uint32_t ctf_str_add (ctf_dict_t *, const char *);

View File

@@ -276,8 +276,9 @@ ctf_lookup_by_name_internal (ctf_dict_t *fp, ctf_dict_t *child,
return ctf_set_typed_errno (fp, ENOMEM); return ctf_set_typed_errno (fp, ENOMEM);
} }
if ((type = ctf_lookup_by_rawhash (fp, lp->ctl_hash, if ((type = (ctf_id_t) (uintptr_t)
fp->ctf_tmp_typeslice)) == 0) ctf_dynhash_lookup (lp->ctl_hash,
fp->ctf_tmp_typeslice)) == 0)
goto notype; goto notype;
break; break;

View File

@@ -740,33 +740,33 @@ init_types (ctf_dict_t *fp, ctf_header_t *cth)
/* Now that we've counted up the number of each type, we can allocate /* Now that we've counted up the number of each type, we can allocate
the hash tables, type translation table, and pointer table. */ the hash tables, type translation table, and pointer table. */
if ((fp->ctf_structs.ctn_readonly if ((fp->ctf_structs
= ctf_hash_create (pop[CTF_K_STRUCT], ctf_hash_string, = ctf_dynhash_create_sized (pop[CTF_K_STRUCT], ctf_hash_string,
ctf_hash_eq_string)) == NULL) ctf_hash_eq_string, NULL, NULL)) == NULL)
return ENOMEM; return ENOMEM;
if ((fp->ctf_unions.ctn_readonly if ((fp->ctf_unions
= ctf_hash_create (pop[CTF_K_UNION], ctf_hash_string, = ctf_dynhash_create_sized (pop[CTF_K_UNION], ctf_hash_string,
ctf_hash_eq_string)) == NULL) ctf_hash_eq_string, NULL, NULL)) == NULL)
return ENOMEM; return ENOMEM;
if ((fp->ctf_enums.ctn_readonly if ((fp->ctf_enums
= ctf_hash_create (pop[CTF_K_ENUM], ctf_hash_string, = ctf_dynhash_create_sized (pop[CTF_K_ENUM], ctf_hash_string,
ctf_hash_eq_string)) == NULL) ctf_hash_eq_string, NULL, NULL)) == NULL)
return ENOMEM; return ENOMEM;
if ((fp->ctf_names.ctn_readonly if ((fp->ctf_names
= ctf_hash_create (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_FUNCTION] +
pop[CTF_K_TYPEDEF] + pop[CTF_K_TYPEDEF] +
pop[CTF_K_POINTER] + pop[CTF_K_POINTER] +
pop[CTF_K_VOLATILE] + pop[CTF_K_VOLATILE] +
pop[CTF_K_CONST] + pop[CTF_K_CONST] +
pop[CTF_K_RESTRICT], pop[CTF_K_RESTRICT],
ctf_hash_string, ctf_hash_string,
ctf_hash_eq_string)) == NULL) ctf_hash_eq_string, NULL, NULL)) == NULL)
return ENOMEM; return ENOMEM;
fp->ctf_txlate = malloc (sizeof (uint32_t) * (fp->ctf_typemax + 1)); fp->ctf_txlate = malloc (sizeof (uint32_t) * (fp->ctf_typemax + 1));
@@ -810,11 +810,10 @@ init_types (ctf_dict_t *fp, ctf_header_t *cth)
root-visible version so that we can be sure to find it when root-visible version so that we can be sure to find it when
checking for conflicting definitions in ctf_add_type(). */ checking for conflicting definitions in ctf_add_type(). */
if (((ctf_hash_lookup_type (fp->ctf_names.ctn_readonly, if (((ctf_dynhash_lookup_type (fp->ctf_names, name)) == 0)
fp, name)) == 0)
|| isroot) || isroot)
{ {
err = ctf_hash_define_type (fp->ctf_names.ctn_readonly, fp, err = ctf_dynhash_insert_type (fp, fp->ctf_names,
LCTF_INDEX_TO_TYPE (fp, id, child), LCTF_INDEX_TO_TYPE (fp, id, child),
tp->ctt_name); tp->ctt_name);
if (err != 0) if (err != 0)
@@ -832,9 +831,9 @@ init_types (ctf_dict_t *fp, ctf_header_t *cth)
if (!isroot) if (!isroot)
break; break;
err = ctf_hash_insert_type (fp->ctf_names.ctn_readonly, fp, err = ctf_dynhash_insert_type (fp, fp->ctf_names,
LCTF_INDEX_TO_TYPE (fp, id, child), LCTF_INDEX_TO_TYPE (fp, id, child),
tp->ctt_name); tp->ctt_name);
if (err != 0) if (err != 0)
return err; return err;
break; break;
@@ -846,9 +845,9 @@ init_types (ctf_dict_t *fp, ctf_header_t *cth)
if (!isroot) if (!isroot)
break; break;
err = ctf_hash_define_type (fp->ctf_structs.ctn_readonly, fp, err = ctf_dynhash_insert_type (fp, fp->ctf_structs,
LCTF_INDEX_TO_TYPE (fp, id, child), LCTF_INDEX_TO_TYPE (fp, id, child),
tp->ctt_name); tp->ctt_name);
if (err != 0) if (err != 0)
return err; return err;
@@ -862,9 +861,9 @@ init_types (ctf_dict_t *fp, ctf_header_t *cth)
if (!isroot) if (!isroot)
break; break;
err = ctf_hash_define_type (fp->ctf_unions.ctn_readonly, fp, err = ctf_dynhash_insert_type (fp, fp->ctf_unions,
LCTF_INDEX_TO_TYPE (fp, id, child), LCTF_INDEX_TO_TYPE (fp, id, child),
tp->ctt_name); tp->ctt_name);
if (err != 0) if (err != 0)
return err; return err;
@@ -874,9 +873,9 @@ init_types (ctf_dict_t *fp, ctf_header_t *cth)
if (!isroot) if (!isroot)
break; break;
err = ctf_hash_define_type (fp->ctf_enums.ctn_readonly, fp, err = ctf_dynhash_insert_type (fp, fp->ctf_enums,
LCTF_INDEX_TO_TYPE (fp, id, child), LCTF_INDEX_TO_TYPE (fp, id, child),
tp->ctt_name); tp->ctt_name);
if (err != 0) if (err != 0)
return err; return err;
@@ -886,27 +885,26 @@ init_types (ctf_dict_t *fp, ctf_header_t *cth)
if (!isroot) if (!isroot)
break; break;
err = ctf_hash_insert_type (fp->ctf_names.ctn_readonly, fp, err = ctf_dynhash_insert_type (fp, fp->ctf_names,
LCTF_INDEX_TO_TYPE (fp, id, child), LCTF_INDEX_TO_TYPE (fp, id, child),
tp->ctt_name); tp->ctt_name);
if (err != 0) if (err != 0)
return err; return err;
break; break;
case CTF_K_FORWARD: case CTF_K_FORWARD:
{ {
ctf_names_t *np = ctf_name_table (fp, tp->ctt_type); ctf_dynhash_t *h = ctf_name_table (fp, tp->ctt_type);
if (!isroot) if (!isroot)
break; break;
/* Only insert forward tags into the given hash if the type or tag /* Only insert forward tags into the given hash if the type or tag
name is not already present. */ name is not already present. */
if (ctf_hash_lookup_type (np->ctn_readonly, fp, name) == 0) if (ctf_dynhash_lookup_type (h, name) == 0)
{ {
err = ctf_hash_insert_type (np->ctn_readonly, fp, err = ctf_dynhash_insert_type (fp, h, LCTF_INDEX_TO_TYPE (fp, id, child),
LCTF_INDEX_TO_TYPE (fp, id, child), tp->ctt_name);
tp->ctt_name);
if (err != 0) if (err != 0)
return err; return err;
} }
@@ -929,15 +927,15 @@ init_types (ctf_dict_t *fp, ctf_header_t *cth)
if (!isroot) if (!isroot)
break; break;
err = ctf_hash_insert_type (fp->ctf_names.ctn_readonly, fp, err = ctf_dynhash_insert_type (fp, fp->ctf_names,
LCTF_INDEX_TO_TYPE (fp, id, child), LCTF_INDEX_TO_TYPE (fp, id, child),
tp->ctt_name); tp->ctt_name);
if (err != 0) if (err != 0)
return err; return err;
break; break;
default: default:
ctf_err_warn (fp, 0, ECTF_CORRUPT, ctf_err_warn (fp, 0, ECTF_CORRUPT,
_("init_types(): unhandled CTF kind: %x"), kind); _("init_static_types(): unhandled CTF kind: %x"), kind);
return ECTF_CORRUPT; return ECTF_CORRUPT;
} }
@@ -946,14 +944,14 @@ init_types (ctf_dict_t *fp, ctf_header_t *cth)
} }
ctf_dprintf ("%lu total types processed\n", fp->ctf_typemax); ctf_dprintf ("%lu total types processed\n", fp->ctf_typemax);
ctf_dprintf ("%u enum names hashed\n", ctf_dprintf ("%zu enum names hashed\n",
ctf_hash_size (fp->ctf_enums.ctn_readonly)); ctf_dynhash_elements (fp->ctf_enums));
ctf_dprintf ("%u struct names hashed (%d long)\n", ctf_dprintf ("%zu struct names hashed (%d long)\n",
ctf_hash_size (fp->ctf_structs.ctn_readonly), nlstructs); ctf_dynhash_elements (fp->ctf_structs), nlstructs);
ctf_dprintf ("%u union names hashed (%d long)\n", ctf_dprintf ("%zu union names hashed (%d long)\n",
ctf_hash_size (fp->ctf_unions.ctn_readonly), nlunions); ctf_dynhash_elements (fp->ctf_unions), nlunions);
ctf_dprintf ("%u base type names hashed\n", ctf_dprintf ("%zu base type names hashed\n",
ctf_hash_size (fp->ctf_names.ctn_readonly)); ctf_dynhash_elements (fp->ctf_names));
return 0; return 0;
} }
@@ -1235,16 +1233,16 @@ void ctf_set_ctl_hashes (ctf_dict_t *fp)
array of type name prefixes and the corresponding ctf_hash to use. */ array of type name prefixes and the corresponding ctf_hash to use. */
fp->ctf_lookups[0].ctl_prefix = "struct"; fp->ctf_lookups[0].ctl_prefix = "struct";
fp->ctf_lookups[0].ctl_len = strlen (fp->ctf_lookups[0].ctl_prefix); fp->ctf_lookups[0].ctl_len = strlen (fp->ctf_lookups[0].ctl_prefix);
fp->ctf_lookups[0].ctl_hash = &fp->ctf_structs; fp->ctf_lookups[0].ctl_hash = fp->ctf_structs;
fp->ctf_lookups[1].ctl_prefix = "union"; fp->ctf_lookups[1].ctl_prefix = "union";
fp->ctf_lookups[1].ctl_len = strlen (fp->ctf_lookups[1].ctl_prefix); fp->ctf_lookups[1].ctl_len = strlen (fp->ctf_lookups[1].ctl_prefix);
fp->ctf_lookups[1].ctl_hash = &fp->ctf_unions; fp->ctf_lookups[1].ctl_hash = fp->ctf_unions;
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 = _CTF_NULLSTR;
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_names;
fp->ctf_lookups[4].ctl_prefix = NULL; fp->ctf_lookups[4].ctl_prefix = NULL;
fp->ctf_lookups[4].ctl_len = 0; fp->ctf_lookups[4].ctl_len = 0;
fp->ctf_lookups[4].ctl_hash = NULL; fp->ctf_lookups[4].ctl_hash = NULL;
@@ -1764,20 +1762,11 @@ ctf_dict_close (ctf_dict_t *fp)
ctf_dtd_delete (fp, dtd); ctf_dtd_delete (fp, dtd);
} }
ctf_dynhash_destroy (fp->ctf_dthash); ctf_dynhash_destroy (fp->ctf_dthash);
if (fp->ctf_flags & LCTF_RDWR)
{ ctf_dynhash_destroy (fp->ctf_structs);
ctf_dynhash_destroy (fp->ctf_structs.ctn_writable); ctf_dynhash_destroy (fp->ctf_unions);
ctf_dynhash_destroy (fp->ctf_unions.ctn_writable); ctf_dynhash_destroy (fp->ctf_enums);
ctf_dynhash_destroy (fp->ctf_enums.ctn_writable); ctf_dynhash_destroy (fp->ctf_names);
ctf_dynhash_destroy (fp->ctf_names.ctn_writable);
}
else
{
ctf_hash_destroy (fp->ctf_structs.ctn_readonly);
ctf_hash_destroy (fp->ctf_unions.ctn_readonly);
ctf_hash_destroy (fp->ctf_enums.ctn_readonly);
ctf_hash_destroy (fp->ctf_names.ctn_readonly);
}
for (dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL; dvd = nvd) for (dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL; dvd = nvd)
{ {

View File

@@ -1203,10 +1203,10 @@ ctf_serialize (ctf_dict_t *fp)
memset (fp->ctf_lookups, 0, sizeof (fp->ctf_lookups)); memset (fp->ctf_lookups, 0, sizeof (fp->ctf_lookups));
memset (&fp->ctf_in_flight_dynsyms, 0, sizeof (fp->ctf_in_flight_dynsyms)); memset (&fp->ctf_in_flight_dynsyms, 0, sizeof (fp->ctf_in_flight_dynsyms));
memset (&fp->ctf_dedup, 0, sizeof (fp->ctf_dedup)); memset (&fp->ctf_dedup, 0, sizeof (fp->ctf_dedup));
fp->ctf_structs.ctn_writable = NULL; fp->ctf_structs = NULL;
fp->ctf_unions.ctn_writable = NULL; fp->ctf_unions = NULL;
fp->ctf_enums.ctn_writable = NULL; fp->ctf_enums = NULL;
fp->ctf_names.ctn_writable = NULL; fp->ctf_names = NULL;
memcpy (&ofp, fp, sizeof (ctf_dict_t)); memcpy (&ofp, fp, sizeof (ctf_dict_t));
memcpy (fp, nfp, sizeof (ctf_dict_t)); memcpy (fp, nfp, sizeof (ctf_dict_t));

View File

@@ -73,6 +73,30 @@ ctf_strptr (ctf_dict_t *fp, uint32_t name)
return (s != NULL ? s : "(?)"); return (s != NULL ? s : "(?)");
} }
/* As above, but return info on what is wrong in more detail.
(Used for type lookups.) */
const char *
ctf_strptr_validate (ctf_dict_t *fp, uint32_t name)
{
const char *str = ctf_strraw (fp, name);
if (str == NULL)
{
if (CTF_NAME_STID (name) == CTF_STRTAB_1
&& fp->ctf_syn_ext_strtab == NULL
&& fp->ctf_str[CTF_NAME_STID (name)].cts_strs == NULL)
{
ctf_set_errno (fp, ECTF_STRTAB);
return NULL;
}
ctf_set_errno (fp, ECTF_BADNAME);
return NULL;
}
return str;
}
/* Remove all refs to a given atom. */ /* Remove all refs to a given atom. */
static void static void
ctf_str_purge_atom_refs (ctf_str_atom_t *atom) ctf_str_purge_atom_refs (ctf_str_atom_t *atom)

View File

@@ -635,22 +635,8 @@ ctf_get_dict (ctf_dict_t *fp, ctf_id_t type)
ctf_id_t ctf_lookup_by_rawname (ctf_dict_t *fp, int kind, const char *name) ctf_id_t ctf_lookup_by_rawname (ctf_dict_t *fp, int kind, const char *name)
{ {
return ctf_lookup_by_rawhash (fp, ctf_name_table (fp, kind), name); return (ctf_id_t) (uintptr_t)
} ctf_dynhash_lookup (ctf_name_table (fp, kind), name);
/* Look up a name in the given name table, in the appropriate hash given the
readability state of the dictionary. The name is a raw, undecorated
identifier. */
ctf_id_t ctf_lookup_by_rawhash (ctf_dict_t *fp, ctf_names_t *np, const char *name)
{
ctf_id_t id;
if (fp->ctf_flags & LCTF_RDWR)
id = (ctf_id_t) (uintptr_t) ctf_dynhash_lookup (np->ctn_writable, name);
else
id = ctf_hash_lookup_type (np->ctn_readonly, fp, name);
return id;
} }
/* Lookup the given type ID and return its name as a new dynamically-allocated /* Lookup the given type ID and return its name as a new dynamically-allocated