diff options
author | Nick Alcock <nick.alcock@oracle.com> | 2021-03-18 12:37:52 +0000 |
---|---|---|
committer | Nick Alcock <nick.alcock@oracle.com> | 2021-03-18 12:40:40 +0000 |
commit | 77d724a7ecdb3fa84557b0ee5c8b7ea949ce56a5 (patch) | |
tree | 0758feb039a9f6e4785f552a594d54cf14631c5e /libctf/ctf-types.c | |
parent | 986e9e3aa03f854bedacef7fac38fe8f009a416c (diff) | |
download | gdb-77d724a7ecdb3fa84557b0ee5c8b7ea949ce56a5.zip gdb-77d724a7ecdb3fa84557b0ee5c8b7ea949ce56a5.tar.gz gdb-77d724a7ecdb3fa84557b0ee5c8b7ea949ce56a5.tar.bz2 |
libctf: eliminate dtd_u, part 4: enums
This is the first tricky one, the first complex multi-entry vlen
containing strings. To handle this in vlen form, we have to handle
pending refs moving around on realloc.
We grow vlen regions using a new ctf_grow_vlen function, and iterate
through the existing enums every time a grow happens, telling the string
machinery the distance between the old and new vlen region and letting
it adjust the pending refs accordingly. (This avoids traversing all
outstanding refs to find the refs that need adjusting, at the cost of
having to traverse one enum: an obvious major performance win.)
Addition of enums themselves (and also structs/unions later) is a bit
trickier than earlier forms, because the type might be being promoted
from a forward, and forwards have no vlen: so we have to spot that and
create it if needed.
Serialization of enums simplifies down to just telling the string
machinery about the string refs; all the enum type-lookup code loses all
its dynamic member lookup complexity entirely.
A new test is added that iterates over (and gets values of) an enum with
enough members to force a round of vlen growth.
libctf/ChangeLog
2021-03-18 Nick Alcock <nick.alcock@oracle.com>
* ctf-impl.h (ctf_dtdef_t) <dtd_vlen_alloc>: New.
(ctf_str_move_pending): Declare.
* ctf-string.c (ctf_str_add_ref_internal): Fix error return.
(ctf_str_move_pending): New.
* ctf-create.c (ctf_grow_vlen): New.
(ctf_dtd_delete): Zero out the vlen_alloc after free. Free the
vlen later: iterate over it and free enum name refs first.
(ctf_add_generic): Populate dtd_vlen_alloc from vlen.
(ctf_add_enum): populate the vlen; do it by hand if promoting
forwards.
(ctf_add_enumerator): Set up the vlen rather than the dmd. Expand
it as needed, repointing string refs via ctf_str_move_pending. Add
the enumerand names as pending strings.
* ctf-serialize.c (ctf_copy_emembers): Remove.
(ctf_emit_type_sect): Copy the vlen into place and ref the
strings.
* ctf-types.c (ctf_enum_next): The dynamic portion now uses
the same code as the non-dynamic.
(ctf_enum_name): Likewise.
(ctf_enum_value): Likewise.
* testsuite/libctf-lookup/enum-many-ctf.c: New test.
* testsuite/libctf-lookup/enum-many.lk: New test.
Diffstat (limited to 'libctf/ctf-types.c')
-rw-r--r-- | libctf/ctf-types.c | 110 |
1 files changed, 31 insertions, 79 deletions
diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c index 1e1ce8e..49264eb 100644 --- a/libctf/ctf-types.c +++ b/libctf/ctf-types.c @@ -318,22 +318,13 @@ ctf_enum_next (ctf_dict_t *fp, ctf_id_t type, ctf_next_t **it, dtd = ctf_dynamic_type (fp, type); i->ctn_iter_fun = (void (*) (void)) ctf_enum_next; - - /* We depend below on the RDWR state indicating whether the DTD-related - fields or the DMD-related fields have been initialized. */ - - assert ((dtd && (fp->ctf_flags & LCTF_RDWR)) - || (!dtd && (!(fp->ctf_flags & LCTF_RDWR)))); + i->ctn_n = LCTF_INFO_VLEN (fp, tp->ctt_info); if (dtd == NULL) - { - i->ctn_n = LCTF_INFO_VLEN (fp, tp->ctt_info); - - i->u.ctn_en = (const ctf_enum_t *) ((uintptr_t) tp + - i->ctn_increment); - } + i->u.ctn_en = (const ctf_enum_t *) ((uintptr_t) tp + + i->ctn_increment); else - i->u.ctn_dmd = ctf_list_next (&dtd->dtd_u.dtu_members); + i->u.ctn_en = (const ctf_enum_t *) dtd->dtd_vlen; *it = i; } @@ -357,27 +348,14 @@ ctf_enum_next (ctf_dict_t *fp, ctf_id_t type, ctf_next_t **it, return NULL; } - if (!(fp->ctf_flags & LCTF_RDWR)) - { - if (i->ctn_n == 0) - goto end_iter; - - name = ctf_strptr (fp, i->u.ctn_en->cte_name); - if (val) - *val = i->u.ctn_en->cte_value; - i->u.ctn_en++; - i->ctn_n--; - } - else - { - if (i->u.ctn_dmd == NULL) - goto end_iter; + if (i->ctn_n == 0) + goto end_iter; - name = i->u.ctn_dmd->dmd_name; - if (val) - *val = i->u.ctn_dmd->dmd_value; - i->u.ctn_dmd = ctf_list_next (i->u.ctn_dmd); - } + name = ctf_strptr (fp, i->u.ctn_en->cte_name); + if (val) + *val = i->u.ctn_en->cte_value; + i->u.ctn_en++; + i->ctn_n--; return name; @@ -1554,35 +1532,24 @@ ctf_enum_name (ctf_dict_t *fp, ctf_id_t type, int value) if (LCTF_INFO_KIND (fp, tp->ctt_info) != CTF_K_ENUM) { - (void) ctf_set_errno (ofp, ECTF_NOTENUM); + ctf_set_errno (ofp, ECTF_NOTENUM); return NULL; } - (void) ctf_get_ctt_size (fp, tp, NULL, &increment); + ctf_get_ctt_size (fp, tp, NULL, &increment); if ((dtd = ctf_dynamic_type (ofp, type)) == NULL) - { - ep = (const ctf_enum_t *) ((uintptr_t) tp + increment); - - for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++) - { - if (ep->cte_value == value) - return (ctf_strptr (fp, ep->cte_name)); - } - } + ep = (const ctf_enum_t *) ((uintptr_t) tp + increment); else - { - ctf_dmdef_t *dmd; + ep = (const ctf_enum_t *) dtd->dtd_vlen; - for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members); - dmd != NULL; dmd = ctf_list_next (dmd)) - { - if (dmd->dmd_value == value) - return dmd->dmd_name; - } + for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++) + { + if (ep->cte_value == value) + return (ctf_strptr (fp, ep->cte_name)); } - (void) ctf_set_errno (ofp, ECTF_NOENUMNAM); + ctf_set_errno (ofp, ECTF_NOENUMNAM); return NULL; } @@ -1590,7 +1557,7 @@ ctf_enum_name (ctf_dict_t *fp, ctf_id_t type, int value) matching name can be found. Otherwise CTF_ERR is returned. */ int -ctf_enum_value (ctf_dict_t * fp, ctf_id_t type, const char *name, int *valp) +ctf_enum_value (ctf_dict_t *fp, ctf_id_t type, const char *name, int *valp) { ctf_dict_t *ofp = fp; const ctf_type_t *tp; @@ -1611,39 +1578,24 @@ ctf_enum_value (ctf_dict_t * fp, ctf_id_t type, const char *name, int *valp) return -1; } - (void) ctf_get_ctt_size (fp, tp, NULL, &increment); - - ep = (const ctf_enum_t *) ((uintptr_t) tp + increment); + ctf_get_ctt_size (fp, tp, NULL, &increment); if ((dtd = ctf_dynamic_type (ofp, type)) == NULL) - { - for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++) - { - if (strcmp (ctf_strptr (fp, ep->cte_name), name) == 0) - { - if (valp != NULL) - *valp = ep->cte_value; - return 0; - } - } - } + ep = (const ctf_enum_t *) ((uintptr_t) tp + increment); else - { - ctf_dmdef_t *dmd; + ep = (const ctf_enum_t *) dtd->dtd_vlen; - for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members); - dmd != NULL; dmd = ctf_list_next (dmd)) + for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++) + { + if (strcmp (ctf_strptr (fp, ep->cte_name), name) == 0) { - if (strcmp (dmd->dmd_name, name) == 0) - { - if (valp != NULL) - *valp = dmd->dmd_value; - return 0; - } + if (valp != NULL) + *valp = ep->cte_value; + return 0; } } - (void) ctf_set_errno (ofp, ECTF_NOENUMNAM); + ctf_set_errno (ofp, ECTF_NOENUMNAM); return -1; } |