--- /dev/null
+#as:
+#source: anonymous-conflicts.c
+#source: anonymous-conflicts-B.c
+#objdump: --ctf
+#ld: -shared --ctf-variables
+#name: Conflicted anonymous struct/union names
+
+.*: +file format .*
+
+Contents of CTF section .ctf:
+
+ Header:
+ Magic number: 0xdff2
+ Version: 5 \(CTF_VERSION_4\)
+#...
+ 0x[0-9a-f]*: \(kind 6\) struct A \(.*
+ \[0x0\] : ID 0x[0-9a-f]*: \(kind 7\) union \(.*
+#...
+ 0x[0-9a-f]*: \(kind 6\) struct A \(.*
+ \[0x0\] : ID 0x[0-9a-f]*: \(kind 7\) union \(.*
+#...
extern int ctf_str_move_refs (ctf_dict_t *fp, void *src, size_t len, void *dest);
extern int ctf_str_add_external (ctf_dict_t *, const char *, uint32_t offset);
extern void ctf_str_remove_ref (ctf_dict_t *, const char *, uint32_t *ref);
+extern void ctf_str_purge_refs (ctf_dict_t *fp);
extern void ctf_str_rollback (ctf_dict_t *, ctf_snapshot_id_t);
extern const ctf_strs_writable_t *ctf_str_write_strtab (ctf_dict_t *);
char **names;
ctf_dict_t *fp;
ctf_dict_t **files;
- size_t i;
+ ssize_t i;
char **dynames;
size_t ndynames;
} ctf_name_list_accum_cb_arg_t;
char *transformed_name = NULL;
ctf_dict_t **files;
FILE *f = NULL;
- size_t i;
+ ssize_t i;
int err;
long fsize;
const char *errloc;
unsigned char *buf = NULL;
+ uint64_t old_parent_strlen, all_strlens = 0;
memset (&arg, 0, sizeof (ctf_name_list_accum_cb_arg_t));
arg.fp = fp;
}
}
- /* No extra outputs? Just write a simple ctf_dict_t. */
+ /* No extra outputs? Just write a simple ctf_dict_t. */
if (arg.i == 0)
{
unsigned char *ret = ctf_write_mem (fp, size, threshold);
}
/* Writing an archive. Stick ourselves (the shared repository, parent of all
- other archives) on the front of it with the default name. */
+ other archives) on the front of it with the default name. (Writing the parent
+ dict out first is essential for strings in child dicts shared with the parent
+ to get their proper offsets.) */
if ((names = realloc (arg.names, sizeof (char *) * (arg.i + 1))) == NULL)
{
errloc = "name reallocation";
memmove (&(arg.files[1]), arg.files, sizeof (ctf_dict_t *) * (arg.i));
arg.files[0] = fp;
+ /* Preserialize everything, doing everything but strtab generation and things that
+ depend on that. */
+ for (i = 0; i < arg.i + 1; i++)
+ {
+ if (ctf_preserialize (arg.files[i]) < 0)
+ {
+ errno = ctf_errno (arg.files[i]);
+ for (i--; i >= 0; i--)
+ ctf_depreserialize (arg.files[i]);
+ errloc = "preserialization";
+ goto err_no;
+ }
+ }
+
+ ctf_dprintf ("Deduplicating strings.\n");
+
+ for (i = 0; i < arg.i; i++)
+ all_strlens += arg.files[i]->ctf_str_prov_offset;
+ old_parent_strlen = arg.files[0]->ctf_str_prov_offset;
+
+ if (ctf_dedup_strings (fp) < 0)
+ {
+ for (i = 0; i < arg.i + 1; i++)
+ ctf_depreserialize (arg.files[i]);
+ errloc = "string deduplication";
+ goto err_str_dedup;
+ }
+
+ ctf_dprintf ("Deduplicated strings: original parent strlen: %zu; "
+ "original lengths: %zu; final length: %zu.\n",
+ (size_t) old_parent_strlen, (size_t) all_strlens,
+ (size_t) arg.files[0]->ctf_str_prov_offset);
+
if ((f = tmpfile ()) == NULL)
{
errloc = "tempfile creation";
threshold)) < 0)
{
errloc = "archive writing";
- ctf_set_errno (fp, err);
- goto err;
+ errno = err;
+ goto err_no;
}
if (fseek (f, 0, SEEK_END) < 0)
err_no:
ctf_set_errno (fp, errno);
-
+ err_str_dedup:
/* Turn off the is-linking flag on all the dicts in this link, as above. */
for (i = 0; i < arg.i; i++)
{
free (did);
}
+ /* The lifetime rules here are delicate. We must destroy the outputs before
+ the atoms (since in a link the outputs contain references to the parent's
+ atoms), but we must destroy the inputs after that (since many type strings
+ ultimately come from the inputs). In addition, if there are
+ ctf_link_outputs, the parent dict's atoms table may have movable refs that
+ refer to the outputs: so purge the refs first, including the movable
+ ones. */
+
+ if (fp->ctf_link_outputs && ctf_dynhash_elements (fp->ctf_link_outputs) > 0)
+ ctf_str_purge_refs (fp);
+
+ ctf_dynhash_destroy (fp->ctf_link_outputs);
+ ctf_dynhash_destroy (fp->ctf_link_out_cu_mapping);
+
ctf_str_free_atoms (fp);
free (fp->ctf_tmp_typeslice);
ctf_dynhash_destroy (fp->ctf_syn_ext_strtab);
ctf_dynhash_destroy (fp->ctf_link_inputs);
- ctf_dynhash_destroy (fp->ctf_link_outputs);
ctf_dynhash_destroy (fp->ctf_link_type_mapping);
ctf_dynhash_destroy (fp->ctf_link_in_cu_mapping);
- ctf_dynhash_destroy (fp->ctf_link_out_cu_mapping);
ctf_dynhash_destroy (fp->ctf_add_processing);
ctf_dedup_fini (fp, NULL, 0);
ctf_dynset_destroy (fp->ctf_dedup_atoms_alloc);