/* CTF type deduplication.
- Copyright (C) 2019-2021 Free Software Foundation, Inc.
+ Copyright (C) 2019-2022 Free Software Foundation, Inc.
This file is part of libctf.
if ((element = ctf_dynhash_lookup (set, key)) == NULL)
{
if ((element = ctf_dynset_create (htab_hash_string,
- ctf_dynset_eq_string,
+ htab_eq_string,
NULL)) == NULL)
return NULL;
if (!fp->ctf_dedup_atoms_alloc)
{
if ((fp->ctf_dedup_atoms_alloc
- = ctf_dynset_create (htab_hash_string, ctf_dynset_eq_string,
+ = ctf_dynset_create (htab_hash_string, htab_eq_string,
free)) == NULL)
return ctf_set_errno (fp, ENOMEM);
}
char hashbuf[CTF_SHA1_SIZE];
const char *hval = NULL;
const char *whaterr;
- int err;
+ int err = 0;
const char *citer = NULL;
ctf_dynset_t *citers = NULL;
whaterr = N_("error updating citers"); \
if (!citers) \
if ((citers = ctf_dynset_create (htab_hash_string, \
- ctf_dynset_eq_string, \
- NULL)) == NULL) \
+ htab_eq_string, \
+ NULL)) == NULL) \
goto oom; \
if (ctf_dynset_cinsert (citers, hval) < 0) \
goto oom; \
if (ctf_type_encoding (input, type, &ep) < 0)
{
whaterr = N_("error getting encoding");
- goto err;
+ goto input_err;
}
ctf_dedup_sha1_add (&hash, &ep, sizeof (ctf_encoding_t), "encoding",
depth);
if (ctf_array_info (input, type, &ar) < 0)
{
whaterr = N_("error getting array info");
- goto err;
+ goto input_err;
}
if ((hval = ctf_dedup_hash_type (fp, input, inputs, parents, input_num,
if (ctf_func_type_info (input, type, &fi) < 0)
{
whaterr = N_("error getting func type info");
- goto err;
+ goto input_err;
}
if ((hval = ctf_dedup_hash_type (fp, input, inputs, parents, input_num,
if ((args = calloc (fi.ctc_argc, sizeof (ctf_id_t))) == NULL)
{
+ err = ENOMEM;
whaterr = N_("error doing memory allocation");
goto err;
}
{
free (args);
whaterr = N_("error getting func arg type");
- goto err;
+ goto input_err;
}
for (j = 0; j < fi.ctc_argc; j++)
{
if (ctf_errno (input) != ECTF_NEXT_END)
{
whaterr = N_("error doing enum member iteration");
- goto err;
+ goto input_err;
}
break;
}
if (ctf_errno (input) != ECTF_NEXT_END)
{
whaterr = N_("error doing struct/union member iteration");
- goto err;
+ goto input_err;
}
break;
}
iterr:
ctf_next_destroy (i);
+ input_err:
+ err = ctf_errno (input);
err:
ctf_sha1_fini (&hash, NULL);
- ctf_err_warn (fp, 0, 0, _("%s (%i): %s: during type hashing for type %lx, "
- "kind %i"), ctf_link_input_name (input),
+ ctf_err_warn (fp, 0, err, _("%s (%i): %s: during type hashing for type %lx, "
+ "kind %i"), ctf_link_input_name (input),
input_num, gettext (whaterr), type, kind);
return NULL;
oom:
if (tp->ctt_name == 0 || !name || name[0] == '\0')
name = NULL;
- /* Treat the unknown kind just like the unimplemented type. */
- if (kind == CTF_K_UNKNOWN)
- return "00000000000000000000";
-
/* Decorate the name appropriately for the namespace it appears in: forwards
appear in the namespace of their referent. */
the most-popular type on insertion, and we want conflicting structs
et al to have all forwards left intact, so the user is notified
that this type is conflicting. TODO: improve this in future by
- setting such forwards non-root-visible.) */
+ setting such forwards non-root-visible.)
+
+ If multiple distinct types are "most common", pick the one that
+ appears first on the link line, and within that, the one with the
+ lowest type ID. (See sort_output_mapping.) */
const void *key;
const void *count;
const char *hval;
long max_hcount = -1;
+ void *max_gid = NULL;
const char *max_hval = NULL;
if (ctf_dynhash_elements (name_counts) <= 1)
while ((err = ctf_dynhash_cnext (name_counts, &j, &key, &count)) == 0)
{
hval = (const char *) key;
+
if ((long int) (uintptr_t) count > max_hcount)
{
max_hcount = (long int) (uintptr_t) count;
max_hval = hval;
+ max_gid = ctf_dynhash_lookup (d->cd_output_first_gid, hval);
+ }
+ else if ((long int) (uintptr_t) count == max_hcount)
+ {
+ void *gid = ctf_dynhash_lookup (d->cd_output_first_gid, hval);
+
+ if (CTF_DEDUP_GID_TO_INPUT(gid) < CTF_DEDUP_GID_TO_INPUT(max_gid)
+ || (CTF_DEDUP_GID_TO_INPUT(gid) == CTF_DEDUP_GID_TO_INPUT(max_gid)
+ && CTF_DEDUP_GID_TO_TYPE(gid) < CTF_DEDUP_GID_TO_TYPE(max_gid)))
+ {
+ max_hval = hval;
+ max_gid = ctf_dynhash_lookup (d->cd_output_first_gid, hval);
+ }
}
}
if (err != ECTF_NEXT_END)
if ((d->cd_conflicting_types
= ctf_dynset_create (htab_hash_string,
- ctf_dynset_eq_string, NULL)) == NULL)
+ htab_eq_string, NULL)) == NULL)
goto oom;
return 0;
const void *k;
ctf_dynset_t *to_mark = NULL;
- if ((to_mark = ctf_dynset_create (htab_hash_string, ctf_dynset_eq_string,
+ if ((to_mark = ctf_dynset_create (htab_hash_string, htab_eq_string,
NULL)) == NULL)
goto err_no;
switch (ctf_type_kind_unsliced (fp, type))
{
case CTF_K_UNKNOWN:
- /* Just skip things of unknown kind. */
- return 0;
case CTF_K_FORWARD:
case CTF_K_INTEGER:
case CTF_K_FLOAT:
void *k;
if ((already_visited = ctf_dynset_create (htab_hash_string,
- ctf_dynset_eq_string,
+ htab_eq_string,
NULL)) == NULL)
return ctf_set_errno (output, ENOMEM);
ctf_parent_name_set (target, _CTF_SECTION);
input->ctf_dedup.cd_output = target;
+ input->ctf_link_in_out = target;
+ target->ctf_link_in_out = input;
}
output_num = input_num;
}
switch (kind)
{
case CTF_K_UNKNOWN:
- /* These are types that CTF cannot encode, marked as such by the compile.
- We intentionally do not re-emit these. */
- new_type = 0;
+ /* These are types that CTF cannot encode, marked as such by the
+ compiler. */
+ errtype = _("unknown type");
+ if ((new_type = ctf_add_unknown (target, isroot, name)) == CTF_ERR)
+ goto err_target;
break;
case CTF_K_FORWARD:
/* This will do nothing if the type to which this forwards already exists,