public inbox for binutils-cvs@sourceware.org
 help / color / mirror / Atom feed
* [binutils-gdb] libctf: fix linking of non-root-visible types
@ 2024-07-31 20:44 Nick Alcock
  0 siblings, 0 replies; only message in thread
From: Nick Alcock @ 2024-07-31 20:44 UTC (permalink / raw)
  To: binutils-cvs

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=87b2f673102884d7c69144c85a26ed5dbaa4f86a

commit 87b2f673102884d7c69144c85a26ed5dbaa4f86a
Author: Nick Alcock <nick.alcock@oracle.com>
Date:   Mon Jul 15 19:42:10 2024 +0100

    libctf: fix linking of non-root-visible types
    
    If you deduplicate non-root-visible types, the resulting type should still
    be non-root-visible! We were promoting all such types to root-visible, and
    re-demoting them only if their names collided (which might happen on
    cu-mapped links if multiple compilation units with conflicting types are
    fused into one child dict).
    
    This "worked" before now, in that linking at least didn't fail (if you don't
    mind having your non-root flag value destroyed if you're adding
    non-root-visible types), but now that conflicting enumerators cause their
    containing enums to become conflicted (enums which might have *different
    names*), this caused the linker to crash when it hit two enumerators with
    conflicting values.
    
    Not testable in ld because cu-mapped links are not exposed to ld, but can be
    tested via direct creation of libraries and calls to ctf_link directly.
    (This also tests the ctf_dump non-root type printout, which before now
    was untested.)
    
    libctf/
            * ctf-dedup.c (ctf_dedup_emit_type): Non-root-visible input types
            should be emitted as non-root-visible output types.
            * testsuite/libctf-writable/ctf-nonroot-linking.c: New test.
            * testsuite/libctf-writable/ctf-nonroot-linking.lk: New test.

Diff:
---
 libctf/ctf-dedup.c                                 |   6 +-
 .../libctf-writable/ctf-nonroot-linking.c          | 127 +++++++++++++++++++++
 .../libctf-writable/ctf-nonroot-linking.lk         |   1 +
 3 files changed, 132 insertions(+), 2 deletions(-)

diff --git a/libctf/ctf-dedup.c b/libctf/ctf-dedup.c
index 6c58daae324..8bfd839524e 100644
--- a/libctf/ctf-dedup.c
+++ b/libctf/ctf-dedup.c
@@ -2640,7 +2640,7 @@ ctf_dedup_emit_type (const char *hval, ctf_dict_t *output, ctf_dict_t **inputs,
   int input_num = CTF_DEDUP_GID_TO_INPUT (id);
   int output_num = (uint32_t) -1;		/* 'shared' */
   int cu_mapped = *(int *)arg;
-  int isroot = 1;
+  int isroot;
   int is_conflicting;
 
   ctf_next_t *i = NULL;
@@ -2708,9 +2708,11 @@ ctf_dedup_emit_type (const char *hval, ctf_dict_t *output, ctf_dict_t **inputs,
     }
 
   name = ctf_strraw (real_input, tp->ctt_name);
+  isroot = LCTF_INFO_ISROOT (real_input, tp->ctt_info);
 
   /* Hide conflicting types, if we were asked to: also hide if a type with this
-     name already exists and is not a forward.  */
+     name already exists and is not a forward, or if this type is hidden on the
+     input.  */
   if (cu_mapped && is_conflicting)
     isroot = 0;
   else if (name
diff --git a/libctf/testsuite/libctf-writable/ctf-nonroot-linking.c b/libctf/testsuite/libctf-writable/ctf-nonroot-linking.c
new file mode 100644
index 00000000000..6edd189b360
--- /dev/null
+++ b/libctf/testsuite/libctf-writable/ctf-nonroot-linking.c
@@ -0,0 +1,127 @@
+/* Make sure linking a non-root-visible type emits a non-root-visible
+   type, rather than silently promoting it to root-visible.  Do it by dumping,
+   thus also testing the {non-root sigils} you get when dumping
+   non-root-visible types.  */
+
+#include <ctf-api.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int
+main (int argc, char *argv[])
+{
+  ctf_dict_t *in1;
+  ctf_dict_t *fp;
+  ctf_dict_t *dump_fp;
+  ctf_archive_t *arc1;
+  ctf_archive_t *final_arc;
+  ctf_sect_t s;
+  ctf_encoding_t encoding = { CTF_INT_SIGNED, 0, sizeof (char) };
+  unsigned char *buf1, *buf2;
+  size_t buf1_sz, buf2_sz;
+  ctf_dump_state_t *dump_state = NULL;
+  ctf_next_t *i = NULL;
+  int err;
+
+  /* Linking does not currently work on mingw because of an unreliable tmpfile
+     implementation on that platform (see
+     https://github.com/msys2/MINGW-packages/issues/18878).  Simply skip for
+     now.  */
+
+#ifdef __MINGW32__
+  printf ("UNSUPPORTED: platform bug breaks ctf_link\n");
+  return 0;
+#else
+
+  if ((fp = ctf_create (&err)) == NULL)
+    goto create_err;
+
+  if ((in1 = ctf_create (&err)) == NULL)
+    goto create_err;
+
+  /* A non-root addition. */
+
+  if ((ctf_add_integer (in1, CTF_ADD_NONROOT, "foo", &encoding)) == CTF_ERR)
+    {
+      fprintf (stderr, "Cannot add: %s\n", ctf_errmsg (ctf_errno (in1)));
+      return 1;
+    }
+
+  /* Write it out and read it back in, to turn it into an archive.
+     This would be unnecessary if ctf_link_add() were public :( */
+  if ((buf1 = ctf_write_mem (in1, &buf1_sz, -1)) == NULL)
+    {
+      fprintf (stderr, "Cannot serialize: %s\n", ctf_errmsg (ctf_errno (in1)));
+      return 1;
+    }
+
+  s.cts_name = "foo";
+  s.cts_data = (void *) buf1;
+  s.cts_size = buf1_sz;
+  s.cts_entsize = 64; /* Unimportant.  */
+
+  if ((arc1 = ctf_arc_bufopen (&s, NULL, NULL, &err)) == NULL)
+    goto open_err;
+
+  ctf_dict_close (in1);
+
+  /* Link!  Even a one-file link does deduplication.  */
+
+  if (ctf_link_add_ctf (fp, arc1, "a") < 0)
+    goto link_err;
+
+  if (ctf_link (fp, 0) < 0)
+    goto link_err;
+
+  /* Write it out.  We need a new buf here, because the archive is still
+     using the other buf.  */
+
+  if ((buf2 = ctf_link_write (fp, &buf2_sz, 4096)) == NULL)
+    goto link_err;
+
+  /* Read it back in.  */
+
+  s.cts_data = (void *) buf2;
+  s.cts_size = buf2_sz;
+
+  if ((final_arc = ctf_arc_bufopen (&s, NULL, NULL, &err)) == NULL)
+    goto open_err;
+
+  /* Dump the types, and search for the {sigils of non-rootedness}.  */
+  while ((dump_fp = ctf_archive_next (final_arc, &i, NULL, 0, &err)) != NULL)
+    {
+      char *dumpstr;
+
+      while ((dumpstr = ctf_dump (dump_fp, &dump_state, CTF_SECT_TYPE,
+				  NULL, NULL)) != NULL)
+	{
+	  if (strchr (dumpstr, '{') != NULL && strchr (dumpstr, '}') != NULL)
+	    printf ("Non-root type found.\n");
+	  free (dumpstr);
+	}
+      ctf_dict_close (dump_fp);
+    }
+  if (err != ECTF_NEXT_END)
+    {
+      fprintf (stderr, "Archive iteration error: %s\n", ctf_errmsg (err));
+      return 1;
+    }
+
+  ctf_arc_close (final_arc);
+  free (buf1);
+  free (buf2);
+  ctf_dict_close (fp);
+  return 0;
+
+ create_err:
+  fprintf (stderr, "Cannot create: %s\n", ctf_errmsg (err));
+  return 1;
+ open_err:
+  fprintf (stderr, "Cannot open: %s\n", ctf_errmsg (err));
+  return 1;
+ link_err:
+  fprintf (stderr, "Cannot link: %s\n", ctf_errmsg (ctf_errno (fp)));
+  return 1;
+#endif
+}
diff --git a/libctf/testsuite/libctf-writable/ctf-nonroot-linking.lk b/libctf/testsuite/libctf-writable/ctf-nonroot-linking.lk
new file mode 100644
index 00000000000..e3edda05c5c
--- /dev/null
+++ b/libctf/testsuite/libctf-writable/ctf-nonroot-linking.lk
@@ -0,0 +1 @@
+Non-root type found.

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2024-07-31 20:44 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-07-31 20:44 [binutils-gdb] libctf: fix linking of non-root-visible types Nick Alcock

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).