forked from Imagelibrary/binutils-gdb
libctf: rethink strtab writeout
This commit finally adjusts strtab writeout so that repeated writeouts, or writeouts of a dict that was read in earlier, only sorts the portion of the strtab that was newly added. There are three intertwined changes here: - pull the contents of strtabs from newly ctf_bufopened dicts into the atoms table, so that future additions will reuse the existing offset etc rather than adding new identical strings - allow the internal ctf_bufopen done by serialization to contribute its existing atoms table, so that existing atoms can be used for the remainder of the open process (like name table construction): this atoms table currente gets thrown away in the mass reassignment done later in ctf_serialize in any case, but it needs to be there during the open. - rewrite ctf_str_write_strtab so that a) it uses iterators rather than ctf_*_iter, reducing pointless structures which serve no other purpose than to implement ordinary variable scope, but more clunkily, and b) retains the existing strtab on the front of the new one, with its sort retained, rather than resorting, so all existing already-written strtab offsets remain valid across the call. This latter change finally permits repeated serializations, and reserializations of ctf_open()ed dicts, to work, but for now we keep the code that prevents that because serialization is about to change again in a way that will make it more obvious that doing such things is safe, and we can take it out then. (There are also some smaller changes like moving the purge of the refs table into ctf_str_write_strtab(), since that's where the changes happen that invalidate it, rather than doing it in ctf_serialize(). We also prohibit something that has never worked, opening a dict and then reporting symbols to it via ctf_link_add_strtab() et al: you must do that to newly-created dicts which have had stuff ctf_link()ed into them. This is very unlikely ever to be a problem in practice: linkers just don't do that sort of thing.) libctf/ * ctf-create.c (ctf_create): Add (temporary) atoms arg. * ctf-impl.h (struct ctf_dict.ctf_dynstrtab): New. (ctf_str_create_atoms): Adjust. (ctf_str_write_strtab): Likewise. (ctf_simple_open_internal): Likewise. * ctf-open.c (ctf_simple_open_internal): Add atoms arg. (ctf_bufopen): Likewise. (ctf_bufopen_internal): Initialize just enough of an atoms table: pre-init from the atoms arg if supplied. (ctf_simple_open): Adjust. * ctf-serialize.c (ctf_serialize): Constify the strtab. Move ref list purging into ctf_str_write_strtab. Initialize the new dict with the old dict's atoms table. Accept the new strtab from ctf_str_write_strtab. Adjust for addition of ctf_dynstrtab. * ctf-string.c (ctf_strraw_explicit): Improve comments. (ctf_str_create_atoms): Prepopulate from an existing atoms table, or alternatively pull in all strings from the strtab and turn them into atoms. (ctf_str_free_atoms): Free the dynstrtab and its strtab. (struct ctf_strtab_write_state): Remove. (ctf_str_count_strtab): Fold this... (ctf_str_populate_sorttab): ... and this... (ctf_str_write_strtab): ... into this. Prepend existing strings to the strtab rather than resorting them (and wrecking their offsets). Keep the dynstrtab updated. Update refs for all atoms with refs, whether or not they are strings newly added to the strtab.
This commit is contained in:
@@ -955,7 +955,7 @@ ctf_serialize (ctf_dict_t *fp)
|
||||
ctf_header_t hdr, *hdrp;
|
||||
ctf_dvdef_t *dvd;
|
||||
ctf_varent_t *dvarents;
|
||||
ctf_strs_writable_t strtab;
|
||||
const ctf_strs_writable_t *strtab;
|
||||
int err;
|
||||
int sym_functions = 0;
|
||||
|
||||
@@ -1090,36 +1090,34 @@ ctf_serialize (ctf_dict_t *fp)
|
||||
assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_stroff);
|
||||
|
||||
/* Construct the final string table and fill out all the string refs with the
|
||||
final offsets. Then purge the refs list, because we're about to move this
|
||||
strtab onto the end of the buf, invalidating all the offsets. */
|
||||
strtab = ctf_str_write_strtab (fp);
|
||||
ctf_str_purge_refs (fp);
|
||||
final offsets. */
|
||||
|
||||
if (strtab.cts_strs == NULL)
|
||||
strtab = ctf_str_write_strtab (fp);
|
||||
|
||||
if (strtab == NULL)
|
||||
goto oom;
|
||||
|
||||
/* Now the string table is constructed, we can sort the buffer of
|
||||
ctf_varent_t's. */
|
||||
ctf_sort_var_arg_cb_t sort_var_arg = { fp, (ctf_strs_t *) &strtab };
|
||||
ctf_sort_var_arg_cb_t sort_var_arg = { fp, (ctf_strs_t *) strtab };
|
||||
ctf_qsort_r (dvarents, nvars, sizeof (ctf_varent_t), ctf_sort_var,
|
||||
&sort_var_arg);
|
||||
|
||||
if ((newbuf = realloc (buf, buf_size + strtab.cts_len)) == NULL)
|
||||
if ((newbuf = realloc (buf, buf_size + strtab->cts_len)) == NULL)
|
||||
goto oom;
|
||||
|
||||
buf = newbuf;
|
||||
memcpy (buf + buf_size, strtab.cts_strs, strtab.cts_len);
|
||||
memcpy (buf + buf_size, strtab->cts_strs, strtab->cts_len);
|
||||
hdrp = (ctf_header_t *) buf;
|
||||
hdrp->cth_strlen = strtab.cts_len;
|
||||
hdrp->cth_strlen = strtab->cts_len;
|
||||
buf_size += hdrp->cth_strlen;
|
||||
free (strtab.cts_strs);
|
||||
|
||||
/* Finally, we are ready to ctf_simple_open() the new dict. If this is
|
||||
successful, we then switch nfp and fp and free the old dict. */
|
||||
|
||||
if ((nfp = ctf_simple_open_internal ((char *) buf, buf_size, NULL, 0,
|
||||
0, NULL, 0, fp->ctf_syn_ext_strtab,
|
||||
&err)) == NULL)
|
||||
fp->ctf_str_atoms, &err)) == NULL)
|
||||
{
|
||||
free (buf);
|
||||
return (ctf_set_errno (fp, err));
|
||||
@@ -1189,9 +1187,11 @@ ctf_serialize (ctf_dict_t *fp)
|
||||
ctf_str_free_atoms (nfp);
|
||||
nfp->ctf_str_atoms = fp->ctf_str_atoms;
|
||||
nfp->ctf_prov_strtab = fp->ctf_prov_strtab;
|
||||
nfp->ctf_dynstrtab = fp->ctf_dynstrtab;
|
||||
nfp->ctf_str_movable_refs = fp->ctf_str_movable_refs;
|
||||
fp->ctf_str_atoms = NULL;
|
||||
fp->ctf_prov_strtab = NULL;
|
||||
fp->ctf_dynstrtab = NULL;
|
||||
fp->ctf_str_movable_refs = NULL;
|
||||
memset (&fp->ctf_dtdefs, 0, sizeof (ctf_list_t));
|
||||
memset (&fp->ctf_errs_warnings, 0, sizeof (ctf_list_t));
|
||||
|
||||
Reference in New Issue
Block a user