mmo.c leak in mmo_make_section
[binutils-gdb.git] / libctf / ctf-dedup.c
index 50da4ac5c1194dafe49365c1adc98c91869d1a3d..dcde3e88c6f150485fb9fce646b423bdaed30122 100644 (file)
@@ -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: