X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=libctf%2Fctf-hash.c;h=71c1f8e4e21e2229de4dcc163bd9d71c0ad25fea;hb=196535a69c8568342e62fdf5e3f5ade04470fd6a;hp=adfe93e5c09a69c5d8cbf164f73e2d59598d1569;hpb=c0754cdd9af6d8259eac5c9daad9f9b0611358dd;p=deliverable%2Fbinutils-gdb.git diff --git a/libctf/ctf-hash.c b/libctf/ctf-hash.c index adfe93e5c0..71c1f8e4e2 100644 --- a/libctf/ctf-hash.c +++ b/libctf/ctf-hash.c @@ -1,5 +1,5 @@ /* Interface to hashtable implementations. - Copyright (C) 2006-2019 Free Software Foundation, Inc. + Copyright (C) 2006-2020 Free Software Foundation, Inc. This file is part of libctf. @@ -82,6 +82,28 @@ ctf_hash_eq_string (const void *a, const void *b) return !strcmp((const char *) hep_a->key, (const char *) hep_b->key); } +/* Hash a type_mapping_key. */ +unsigned int +ctf_hash_type_mapping_key (const void *ptr) +{ + ctf_helem_t *hep = (ctf_helem_t *) ptr; + ctf_link_type_mapping_key_t *k = (ctf_link_type_mapping_key_t *) hep->key; + + return htab_hash_pointer (k->cltm_fp) + 59 * htab_hash_pointer ((void *) k->cltm_idx); +} + +int +ctf_hash_eq_type_mapping_key (const void *a, const void *b) +{ + ctf_helem_t *hep_a = (ctf_helem_t *) a; + ctf_helem_t *hep_b = (ctf_helem_t *) b; + ctf_link_type_mapping_key_t *key_a = (ctf_link_type_mapping_key_t *) hep_a->key; + ctf_link_type_mapping_key_t *key_b = (ctf_link_type_mapping_key_t *) hep_b->key; + + return (key_a->cltm_fp == key_b->cltm_fp) + && (key_a->cltm_idx == key_b->cltm_idx); +} + /* The dynhash, used for hashes whose size is not known at creation time. */ /* Free a single ctf_helem. */ @@ -130,7 +152,9 @@ ctf_hashtab_lookup (struct htab *htab, const void *key, enum insert_option inser } static ctf_helem_t * -ctf_hashtab_insert (struct htab *htab, void *key, void *value) +ctf_hashtab_insert (struct htab *htab, void *key, void *value, + ctf_hash_free_fun key_free, + ctf_hash_free_fun value_free) { ctf_helem_t **slot; @@ -147,8 +171,15 @@ ctf_hashtab_insert (struct htab *htab, void *key, void *value) *slot = malloc (sizeof (ctf_helem_t)); if (!*slot) return NULL; - (*slot)->key = key; } + else + { + if (key_free) + key_free ((*slot)->key); + if (value_free) + value_free ((*slot)->value); + } + (*slot)->key = key; (*slot)->value = value; return *slot; } @@ -158,13 +189,14 @@ ctf_dynhash_insert (ctf_dynhash_t *hp, void *key, void *value) { ctf_helem_t *slot; - slot = ctf_hashtab_insert (hp->htab, key, value); + slot = ctf_hashtab_insert (hp->htab, key, value, + hp->key_free, hp->value_free); if (!slot) return errno; /* We need to keep the key_free and value_free around in each item because the - del function has no visiblity into the hash as a whole, only into the + del function has no visibility into the hash as a whole, only into the individual items. */ slot->key_free = hp->key_free; @@ -176,7 +208,14 @@ ctf_dynhash_insert (ctf_dynhash_t *hp, void *key, void *value) void ctf_dynhash_remove (ctf_dynhash_t *hp, const void *key) { - htab_remove_elt (hp->htab, (void *) key); + ctf_helem_t hep = { (void *) key, NULL, NULL, NULL }; + htab_remove_elt (hp->htab, &hep); +} + +void +ctf_dynhash_empty (ctf_dynhash_t *hp) +{ + htab_empty (hp->htab); } void * @@ -192,6 +231,55 @@ ctf_dynhash_lookup (ctf_dynhash_t *hp, const void *key) return NULL; } +typedef struct ctf_traverse_cb_arg +{ + ctf_hash_iter_f fun; + void *arg; +} ctf_traverse_cb_arg_t; + +static int +ctf_hashtab_traverse (void **slot, void *arg_) +{ + ctf_helem_t *helem = *((ctf_helem_t **) slot); + ctf_traverse_cb_arg_t *arg = (ctf_traverse_cb_arg_t *) arg_; + + arg->fun (helem->key, helem->value, arg->arg); + return 1; +} + +void +ctf_dynhash_iter (ctf_dynhash_t *hp, ctf_hash_iter_f fun, void *arg_) +{ + ctf_traverse_cb_arg_t arg = { fun, arg_ }; + htab_traverse (hp->htab, ctf_hashtab_traverse, &arg); +} + +typedef struct ctf_traverse_remove_cb_arg +{ + struct htab *htab; + ctf_hash_iter_remove_f fun; + void *arg; +} ctf_traverse_remove_cb_arg_t; + +static int +ctf_hashtab_traverse_remove (void **slot, void *arg_) +{ + ctf_helem_t *helem = *((ctf_helem_t **) slot); + ctf_traverse_remove_cb_arg_t *arg = (ctf_traverse_remove_cb_arg_t *) arg_; + + if (arg->fun (helem->key, helem->value, arg->arg)) + htab_clear_slot (arg->htab, slot); + return 1; +} + +void +ctf_dynhash_iter_remove (ctf_dynhash_t *hp, ctf_hash_iter_remove_f fun, + void *arg_) +{ + ctf_traverse_remove_cb_arg_t arg = { hp->htab, fun, arg_ }; + htab_traverse (hp->htab, ctf_hashtab_traverse_remove, &arg); +} + void ctf_dynhash_destroy (ctf_dynhash_t *hp) { @@ -221,23 +309,25 @@ int ctf_hash_insert_type (ctf_hash_t *hp, ctf_file_t *fp, uint32_t type, uint32_t name) { - ctf_strs_t *ctsp = &fp->ctf_str[CTF_NAME_STID (name)]; - const char *str = ctsp->cts_strs + CTF_NAME_OFFSET (name); + const char *str = ctf_strraw (fp, name); if (type == 0) return EINVAL; - if (ctsp->cts_strs == NULL) + if (str == NULL + && CTF_NAME_STID (name) == CTF_STRTAB_1 + && fp->ctf_syn_ext_strtab == NULL + && fp->ctf_str[CTF_NAME_STID (name)].cts_strs == NULL) return ECTF_STRTAB; - if (ctsp->cts_len <= CTF_NAME_OFFSET (name)) + if (str == NULL) return ECTF_BADNAME; if (str[0] == '\0') return 0; /* Just ignore empty strings on behalf of caller. */ if (ctf_hashtab_insert ((struct htab *) hp, (char *) str, - (void *) (ptrdiff_t) type) != NULL) + (void *) (ptrdiff_t) type, NULL, NULL) != NULL) return 0; return errno; }