X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=libctf%2Fctf-string.c;h=936307cf6e564985674d3530c50f68822143e1f9;hb=13835d88dc51497b9bd68dc1f394ca0de099a380;hp=91ad2e36db7f76e8c1289c24ea077108c92fccca;hpb=ee87f50b8d2a0599675657a9fd2774c08261b29c;p=binutils-gdb.git diff --git a/libctf/ctf-string.c b/libctf/ctf-string.c index 91ad2e36db7..936307cf6e5 100644 --- a/libctf/ctf-string.c +++ b/libctf/ctf-string.c @@ -1,5 +1,5 @@ /* CTF string table management. - Copyright (C) 2019-2021 Free Software Foundation, Inc. + Copyright (C) 2019-2022 Free Software Foundation, Inc. This file is part of libctf. @@ -19,6 +19,7 @@ #include #include +#include /* Convert an encoded CTF string name into a pointer to a C string, using an explicit internal strtab rather than the fp-based one. */ @@ -103,7 +104,7 @@ ctf_str_create_atoms (ctf_dict_t *fp) { fp->ctf_str_atoms = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string, free, ctf_str_free_atom); - if (fp->ctf_str_atoms == NULL) + if (!fp->ctf_str_atoms) return -ENOMEM; if (!fp->ctf_prov_strtab) @@ -113,6 +114,13 @@ ctf_str_create_atoms (ctf_dict_t *fp) if (!fp->ctf_prov_strtab) goto oom_prov_strtab; + if (!fp->ctf_str_pending_ref) + fp->ctf_str_pending_ref = ctf_dynset_create (htab_hash_pointer, + htab_eq_pointer, + NULL); + if (!fp->ctf_str_pending_ref) + goto oom_str_pending_ref; + errno = 0; ctf_str_add (fp, ""); if (errno == ENOMEM) @@ -123,6 +131,9 @@ ctf_str_create_atoms (ctf_dict_t *fp) oom_str_add: ctf_dynhash_destroy (fp->ctf_prov_strtab); fp->ctf_prov_strtab = NULL; + oom_str_pending_ref: + ctf_dynset_destroy (fp->ctf_str_pending_ref); + fp->ctf_str_pending_ref = NULL; oom_prov_strtab: ctf_dynhash_destroy (fp->ctf_str_atoms); fp->ctf_str_atoms = NULL; @@ -135,8 +146,13 @@ ctf_str_free_atoms (ctf_dict_t *fp) { ctf_dynhash_destroy (fp->ctf_prov_strtab); ctf_dynhash_destroy (fp->ctf_str_atoms); + ctf_dynset_destroy (fp->ctf_str_pending_ref); } +#define CTF_STR_ADD_REF 0x1 +#define CTF_STR_MAKE_PROVISIONAL 0x2 +#define CTF_STR_PENDING_REF 0x4 + /* Add a string to the atoms table, copying the passed-in string. Return the atom added. Return NULL only when out of memory (and do not touch the passed-in string in that case). Possibly augment the ref list with the @@ -144,7 +160,7 @@ ctf_str_free_atoms (ctf_dict_t *fp) provisional strtab. */ static ctf_str_atom_t * ctf_str_add_ref_internal (ctf_dict_t *fp, const char *str, - int add_ref, int make_provisional, uint32_t *ref) + int flags, uint32_t *ref) { char *newstr = NULL; ctf_str_atom_t *atom = NULL; @@ -152,7 +168,7 @@ ctf_str_add_ref_internal (ctf_dict_t *fp, const char *str, atom = ctf_dynhash_lookup (fp->ctf_str_atoms, str); - if (add_ref) + if (flags & CTF_STR_ADD_REF) { if ((aref = malloc (sizeof (struct ctf_str_atom_ref))) == NULL) return NULL; @@ -161,8 +177,9 @@ ctf_str_add_ref_internal (ctf_dict_t *fp, const char *str, if (atom) { - if (add_ref) + if (flags & CTF_STR_ADD_REF) { + ctf_dynset_remove (fp->ctf_str_pending_ref, (void *) ref); ctf_list_append (&atom->csa_refs, aref); fp->ctf_str_num_refs++; } @@ -182,7 +199,7 @@ ctf_str_add_ref_internal (ctf_dict_t *fp, const char *str, atom->csa_str = newstr; atom->csa_snapshot_id = fp->ctf_snapshots; - if (make_provisional) + if (flags & CTF_STR_MAKE_PROVISIONAL) { atom->csa_offset = fp->ctf_str_prov_offset; @@ -193,8 +210,14 @@ ctf_str_add_ref_internal (ctf_dict_t *fp, const char *str, fp->ctf_str_prov_offset += strlen (atom->csa_str) + 1; } - if (add_ref) + if (flags & CTF_STR_PENDING_REF) { + if (ctf_dynset_insert (fp->ctf_str_pending_ref, (void *) ref) < 0) + goto oom; + } + else if (flags & CTF_STR_ADD_REF) + { + ctf_dynset_remove (fp->ctf_str_pending_ref, (void *) ref); ctf_list_append (&atom->csa_refs, aref); fp->ctf_str_num_refs++; } @@ -206,6 +229,7 @@ ctf_str_add_ref_internal (ctf_dict_t *fp, const char *str, free (atom); free (aref); free (newstr); + ctf_set_errno (fp, ENOMEM); return NULL; } @@ -222,7 +246,7 @@ ctf_str_add (ctf_dict_t *fp, const char *str) if (!str) str = ""; - atom = ctf_str_add_ref_internal (fp, str, FALSE, TRUE, 0); + atom = ctf_str_add_ref_internal (fp, str, CTF_STR_MAKE_PROVISIONAL, 0); if (!atom) return 0; @@ -240,13 +264,47 @@ ctf_str_add_ref (ctf_dict_t *fp, const char *str, uint32_t *ref) if (!str) str = ""; - atom = ctf_str_add_ref_internal (fp, str, TRUE, TRUE, ref); + atom = ctf_str_add_ref_internal (fp, str, CTF_STR_ADD_REF + | CTF_STR_MAKE_PROVISIONAL, ref); if (!atom) return 0; return atom->csa_offset; } +/* Like ctf_str_add_ref(), but notes that this memory location must be added as + a ref by a later serialization phase, rather than adding it itself. */ +uint32_t +ctf_str_add_pending (ctf_dict_t *fp, const char *str, uint32_t *ref) +{ + ctf_str_atom_t *atom; + + if (!str) + str = ""; + + atom = ctf_str_add_ref_internal (fp, str, CTF_STR_PENDING_REF + | CTF_STR_MAKE_PROVISIONAL, ref); + if (!atom) + return 0; + + return atom->csa_offset; +} + +/* Note that a pending ref now located at NEW_REF has moved by BYTES bytes. */ +int +ctf_str_move_pending (ctf_dict_t *fp, uint32_t *new_ref, ptrdiff_t bytes) +{ + if (bytes == 0) + return 0; + + if (ctf_dynset_insert (fp->ctf_str_pending_ref, (void *) new_ref) < 0) + return (ctf_set_errno (fp, ENOMEM)); + + ctf_dynset_remove (fp->ctf_str_pending_ref, + (void *) ((signed char *) new_ref - bytes)); + return 0; +} + /* Add an external strtab reference at OFFSET. Returns zero if the addition failed, nonzero otherwise. */ int @@ -257,7 +315,7 @@ ctf_str_add_external (ctf_dict_t *fp, const char *str, uint32_t offset) if (!str) str = ""; - atom = ctf_str_add_ref_internal (fp, str, FALSE, FALSE, 0); + atom = ctf_str_add_ref_internal (fp, str, 0, 0); if (!atom) return 0; @@ -307,6 +365,8 @@ ctf_str_remove_ref (ctf_dict_t *fp, const char *str, uint32_t *ref) free (aref); } } + + ctf_dynset_remove (fp->ctf_str_pending_ref, (void *) ref); } /* A ctf_dynhash_iter_remove() callback that removes atoms later than a given