X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=libctf%2Fctf-dedup.c;h=dcde3e88c6f150485fb9fce646b423bdaed30122;hb=7a1bc25b9d2c3f066000d07b5254d20367b6da0f;hp=50da4ac5c1194dafe49365c1adc98c91869d1a3d;hpb=f5060e56338f837f3bb218da50297938d493bacc;p=binutils-gdb.git diff --git a/libctf/ctf-dedup.c b/libctf/ctf-dedup.c index 50da4ac5c11..dcde3e88c6f 100644 --- a/libctf/ctf-dedup.c +++ b/libctf/ctf-dedup.c @@ -1,5 +1,5 @@ /* 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. @@ -352,7 +352,7 @@ make_set_element (ctf_dynhash_t *set, const void *key) 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; @@ -376,7 +376,7 @@ ctf_dedup_atoms_init (ctf_dict_t *fp) 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); } @@ -572,7 +572,7 @@ ctf_dedup_rhash_type (ctf_dict_t *fp, ctf_dict_t *input, ctf_dict_t **inputs, 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; @@ -584,12 +584,13 @@ ctf_dedup_rhash_type (ctf_dict_t *fp, ctf_dict_t *input, ctf_dict_t **inputs, 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; \ - } while (0) + } \ + while (0) /* If this is a named struct or union or a forward to one, and this is a child traversal, treat this type as if it were a forward -- do not recurse to @@ -696,7 +697,7 @@ ctf_dedup_rhash_type (ctf_dict_t *fp, ctf_dict_t *input, ctf_dict_t **inputs, 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); @@ -751,7 +752,7 @@ ctf_dedup_rhash_type (ctf_dict_t *fp, ctf_dict_t *input, ctf_dict_t **inputs, citer = hval; if ((dtd = ctf_dynamic_type (input, type)) != NULL) - slice = &dtd->dtd_u.dtu_slice; + slice = (ctf_slice_t *) dtd->dtd_vlen; else slice = (ctf_slice_t *) ((uintptr_t) tp + increment); @@ -769,7 +770,7 @@ ctf_dedup_rhash_type (ctf_dict_t *fp, ctf_dict_t *input, ctf_dict_t **inputs, 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, @@ -807,7 +808,7 @@ ctf_dedup_rhash_type (ctf_dict_t *fp, ctf_dict_t *input, ctf_dict_t **inputs, 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, @@ -827,6 +828,7 @@ ctf_dedup_rhash_type (ctf_dict_t *fp, ctf_dict_t *input, ctf_dict_t **inputs, if ((args = calloc (fi.ctc_argc, sizeof (ctf_id_t))) == NULL) { + err = ENOMEM; whaterr = N_("error doing memory allocation"); goto err; } @@ -835,7 +837,7 @@ ctf_dedup_rhash_type (ctf_dict_t *fp, ctf_dict_t *input, ctf_dict_t **inputs, { free (args); whaterr = N_("error getting func arg type"); - goto err; + goto input_err; } for (j = 0; j < fi.ctc_argc; j++) { @@ -870,7 +872,7 @@ ctf_dedup_rhash_type (ctf_dict_t *fp, ctf_dict_t *input, ctf_dict_t **inputs, if (ctf_errno (input) != ECTF_NEXT_END) { whaterr = N_("error doing enum member iteration"); - goto err; + goto input_err; } break; } @@ -915,7 +917,7 @@ ctf_dedup_rhash_type (ctf_dict_t *fp, ctf_dict_t *input, ctf_dict_t **inputs, if (ctf_errno (input) != ECTF_NEXT_END) { whaterr = N_("error doing struct/union member iteration"); - goto err; + goto input_err; } break; } @@ -970,10 +972,12 @@ ctf_dedup_rhash_type (ctf_dict_t *fp, ctf_dict_t *input, ctf_dict_t **inputs, 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: @@ -1060,10 +1064,6 @@ ctf_dedup_hash_type (ctf_dict_t *fp, ctf_dict_t *input, 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. */ @@ -1502,12 +1502,17 @@ ctf_dedup_detect_name_ambiguity (ctf_dict_t *fp, ctf_dict_t **inputs) 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) @@ -1517,10 +1522,24 @@ ctf_dedup_detect_name_ambiguity (ctf_dict_t *fp, ctf_dict_t **inputs) 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) @@ -1656,7 +1675,7 @@ ctf_dedup_init (ctf_dict_t *fp) 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; @@ -1814,7 +1833,7 @@ ctf_dedup_conflictify_unshared (ctf_dict_t *output, ctf_dict_t **inputs) 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; @@ -1924,15 +1943,17 @@ ctf_dedup (ctf_dict_t *output, ctf_dict_t **inputs, uint32_t ninputs, while ((id = ctf_type_next (inputs[i], &it, NULL, 1)) != CTF_ERR) { - ctf_dedup_hash_type (output, inputs[i], inputs, parents, - i, id, 0, 0, ctf_dedup_populate_mappings); + if (ctf_dedup_hash_type (output, inputs[i], inputs, + parents, i, id, 0, 0, + ctf_dedup_populate_mappings) == NULL) + goto err; /* errno is set for us. */ } if (ctf_errno (inputs[i]) != ECTF_NEXT_END) { ctf_set_errno (output, ctf_errno (inputs[i])); ctf_err_warn (output, 0, 0, _("iteration failure " "computing type hashes")); - return -1; + goto err; } } @@ -1943,7 +1964,7 @@ ctf_dedup (ctf_dict_t *output, ctf_dict_t **inputs, uint32_t ninputs, ctf_dprintf ("Detecting type name ambiguity\n"); if (ctf_dedup_detect_name_ambiguity (output, inputs) < 0) - return -1; /* errno is set for us. */ + goto err; /* errno is set for us. */ /* If the link mode is CTF_LINK_SHARE_DUPLICATED, we change any unconflicting types whose output mapping references only one input dict into a @@ -1953,7 +1974,7 @@ ctf_dedup (ctf_dict_t *output, ctf_dict_t **inputs, uint32_t ninputs, { ctf_dprintf ("Conflictifying unshared types\n"); if (ctf_dedup_conflictify_unshared (output, inputs) < 0) - return -1; /* errno is set for us. */ + goto err; /* errno is set for us. */ } return 0; @@ -2027,48 +2048,48 @@ ctf_dedup_rwalk_one_output_mapping (ctf_dict_t *output, times, which is worse. */ #define CTF_TYPE_WALK(type, errlabel, errmsg) \ - do { \ - void *type_id; \ - const char *hashval; \ - int cited_type_input_num = input_num; \ + do \ + { \ + void *type_id; \ + const char *hashval; \ + int cited_type_input_num = input_num; \ \ - if ((fp->ctf_flags & LCTF_CHILD) && (LCTF_TYPE_ISPARENT (fp, type))) \ - cited_type_input_num = parents[input_num]; \ + if ((fp->ctf_flags & LCTF_CHILD) && (LCTF_TYPE_ISPARENT (fp, type))) \ + cited_type_input_num = parents[input_num]; \ \ - type_id = CTF_DEDUP_GID (output, cited_type_input_num, type); \ + type_id = CTF_DEDUP_GID (output, cited_type_input_num, type); \ \ - if (type == 0) \ - { \ - ctf_dprintf ("Walking: unimplemented type\n"); \ - break; \ - } \ + if (type == 0) \ + { \ + ctf_dprintf ("Walking: unimplemented type\n"); \ + break; \ + } \ \ - ctf_dprintf ("Looking up ID %i/%lx in type hashes\n", \ - cited_type_input_num, type); \ - hashval = ctf_dynhash_lookup (d->cd_type_hashes, type_id); \ - if (!ctf_assert (output, hashval)) \ - { \ - whaterr = N_("error looking up ID in type hashes"); \ - goto errlabel; \ - } \ - ctf_dprintf ("ID %i/%lx has hash %s\n", cited_type_input_num, type, \ - hashval); \ + ctf_dprintf ("Looking up ID %i/%lx in type hashes\n", \ + cited_type_input_num, type); \ + hashval = ctf_dynhash_lookup (d->cd_type_hashes, type_id); \ + if (!ctf_assert (output, hashval)) \ + { \ + whaterr = N_("error looking up ID in type hashes"); \ + goto errlabel; \ + } \ + ctf_dprintf ("ID %i/%lx has hash %s\n", cited_type_input_num, type, \ + hashval); \ \ - ret = ctf_dedup_rwalk_output_mapping (output, inputs, ninputs, parents, \ - already_visited, hashval, \ - visit_fun, arg, depth); \ - if (ret < 0) \ - { \ - whaterr = errmsg; \ - goto errlabel; \ - } \ - } while (0) + ret = ctf_dedup_rwalk_output_mapping (output, inputs, ninputs, parents, \ + already_visited, hashval, \ + visit_fun, arg, depth); \ + if (ret < 0) \ + { \ + whaterr = errmsg; \ + goto errlabel; \ + } \ + } \ + while (0) 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: @@ -2349,7 +2370,7 @@ ctf_dedup_walk_output_mapping (ctf_dict_t *output, ctf_dict_t **inputs, 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); @@ -2650,6 +2671,8 @@ ctf_dedup_emit_type (const char *hval, ctf_dict_t *output, ctf_dict_t **inputs, 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; } @@ -2694,9 +2717,11 @@ ctf_dedup_emit_type (const char *hval, ctf_dict_t *output, ctf_dict_t **inputs, 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, @@ -2882,7 +2907,10 @@ ctf_dedup_emit_type (const char *hval, ctf_dict_t *output, ctf_dict_t **inputs, id, out_id); /* Record the need to emit the members of this structure later. */ if (ctf_dynhash_insert (d->cd_emission_struct_members, id, out_id) < 0) - goto err_target; + { + ctf_set_errno (target, errno); + goto err_target; + } break; } default: