public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH V5] CTF: multi-CU and archive support
@ 2021-05-18  0:20 Weimin Pan
  2021-05-25  0:52 ` [PING][PATCH " Wei-min Pan
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Weimin Pan @ 2021-05-18  0:20 UTC (permalink / raw)
  To: gdb-patches

[Changes from V4:  
 - Treat CTF archives as CUs over dependencies to avoid over-expanding
   psymtabs, as Tom Tromey pointed out. 
 - Avoid calling ctf_dict_close more than once on a dictionary.]

Now gdb is capable of debugging executable, which consists of multiple
compilation units (CUs) with the CTF debug info. An executable could
potentially have one or more archives, which, in CTF context, contain
conflicting types.

all changes were made in ctfread.c in which elfctf_build_psymtabs was
modified to handle archives, via the ctf archive iterator and its callback
build_ctf_archive_member and scan_partial_symbols was modified to scan
archives, which are treated as subfiles, to build the psymtabs.

Also changes were made to handle CTF's data object section and function
info section which now share the same format of their contents - an array
of type IDs. New functions ctf_psymtab_add_stt_entries, which is called by
ctf_psymtab_add_stt_obj and ctf_psymtab_add_stt_func, and add_stt_entries,
which is called by add_stt_obj and add_stt_func when setting up psymtabs
and full symtab, respectively.
---
 gdb/ctfread.c                             | 311 +++++++++++++++++-------------
 gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c |  18 ++
 gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c |  16 ++
 gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c |   3 +
 gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c |   4 +
 gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp |  43 +++++
 gdb/testsuite/gdb.ctf/ctf-a.c             |  32 +++
 gdb/testsuite/gdb.ctf/ctf-a.h             |  22 +++
 gdb/testsuite/gdb.ctf/ctf-b.c             |  25 +++
 gdb/testsuite/gdb.ctf/ctf-b.h             |  22 +++
 gdb/testsuite/gdb.ctf/ctf-c.c             |  25 +++
 gdb/testsuite/gdb.ctf/ctf-c.h             |  21 ++
 gdb/testsuite/gdb.ctf/multi.exp           |  42 ++++
 13 files changed, 453 insertions(+), 131 deletions(-)
 create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c
 create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c
 create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c
 create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c
 create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp
 create mode 100644 gdb/testsuite/gdb.ctf/ctf-a.c
 create mode 100644 gdb/testsuite/gdb.ctf/ctf-a.h
 create mode 100644 gdb/testsuite/gdb.ctf/ctf-b.c
 create mode 100644 gdb/testsuite/gdb.ctf/ctf-b.h
 create mode 100644 gdb/testsuite/gdb.ctf/ctf-c.c
 create mode 100644 gdb/testsuite/gdb.ctf/ctf-c.h
 create mode 100644 gdb/testsuite/gdb.ctf/multi.exp

diff --git a/gdb/ctfread.c b/gdb/ctfread.c
index 23e859a..1939f40 100644
--- a/gdb/ctfread.c
+++ b/gdb/ctfread.c
@@ -117,6 +117,7 @@ struct ctf_context
   struct objfile *of;
   psymtab_storage *partial_symtabs;
   partial_symtab *pst;
+  ctf_archive_t *arc;
   struct buildsym_compunit *builder;
 };
 
@@ -166,6 +167,16 @@ struct ctf_field_info
   std::vector<struct decl_field> nested_types_list;
 };
 
+/* Data held for a translation unit.  */
+
+struct ctf_per_tu_data
+{
+  ctf_dict_t *fp;
+  struct objfile *of;
+  ctf_archive_t *arc;
+  psymtab_storage *pss;
+  psymbol_functions *psf;
+};
 
 /* Local function prototypes */
 
@@ -245,10 +256,8 @@ struct ctf_tid_and_type
   ids.tid = tid;
   ids.type = typ;
   slot = (struct ctf_tid_and_type **) htab_find_slot (htab, &ids, INSERT);
-  if (*slot)
-    complaint (_("An internal GDB problem: ctf_ id_t %ld type already set"),
-	       (tid));
-  *slot = XOBNEW (&of->objfile_obstack, struct ctf_tid_and_type);
+  if (*slot == nullptr)
+    *slot = XOBNEW (&of->objfile_obstack, struct ctf_tid_and_type);
   **slot = ids;
   return typ;
 }
@@ -510,7 +519,7 @@ struct ctf_tid_and_type
 	    break;
 	}
 
-      add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
+      add_symbol_to_list (sym, ccp->builder->get_file_symbols ());
     }
 
   return sym;
@@ -1143,7 +1152,8 @@ struct ctf_tid_and_type
 	if (type)
 	  {
 	    sym = new_symbol (ccp, type, id);
-	    sym->compute_and_set_names (name, false, ccp->of->per_bfd);
+	    if (sym)
+	      sym->compute_and_set_names (name, false, ccp->of->per_bfd);
 	  }
 	break;
       case CTF_K_STRUCT:
@@ -1160,7 +1170,7 @@ struct ctf_tid_and_type
 	SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
 	SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT;
 	sym->compute_and_set_names (name, false, ccp->of->per_bfd);
-	add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
+	add_symbol_to_list (sym, ccp->builder->get_file_symbols ());
 	break;
       default:
 	complaint (_("ctf_add_var_cb: kind unsupported (%d)"), kind);
@@ -1173,81 +1183,48 @@ struct ctf_tid_and_type
   return 0;
 }
 
-/* Add an ELF STT_OBJ symbol with index IDX to the symbol table.  */
+/* Add entries in either data objects or function info section, controlled
+   by FUNCTIONS.  */
 
-static struct symbol *
-add_stt_obj (struct ctf_context *ccp, unsigned long idx)
+static void
+add_stt_entries (struct ctf_context *ccp, int functions)
 {
-  struct symbol *sym;
-  struct type *type;
+  ctf_next_t *i = nullptr;
+  const char *tname;
   ctf_id_t tid;
+  struct symbol *sym = nullptr;
+  struct type *type;
 
-  if ((tid = ctf_lookup_by_symbol (ccp->fp, idx)) == CTF_ERR)
-    return nullptr;
-
-  type = fetch_tid_type (ccp, tid);
-  if (type == nullptr)
-    return nullptr;
-
-  sym = new_symbol (ccp, type, tid);
-
-  return sym;
+  while ((tid = ctf_symbol_next (ccp->fp, &i, &tname, functions)) != CTF_ERR)
+    {
+      type = get_tid_type (ccp->of, tid);
+      if (type == nullptr)
+	continue;
+      sym = new (&ccp->of->objfile_obstack) symbol;
+      OBJSTAT (ccp->of, n_syms++);
+      SYMBOL_TYPE (sym) = type;
+      SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
+      SYMBOL_ACLASS_INDEX (sym) = LOC_STATIC;
+      sym->compute_and_set_names (tname, false, ccp->of->per_bfd);
+      add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
+      set_symbol_address (ccp->of, sym, tname);
+    }
 }
 
-/* Add an ELF STT_FUNC symbol with index IDX to the symbol table.  */
+/* Add entries in data objects section.  */
 
-static struct symbol *
-add_stt_func (struct ctf_context *ccp, unsigned long idx)
+static void
+add_stt_obj (struct ctf_context *ccp)
 {
-  struct type *ftype, *atyp, *rettyp;
-  struct symbol *sym;
-  ctf_funcinfo_t finfo;
-  ctf_id_t argv[32];
-  uint32_t argc;
-  ctf_id_t tid;
-  struct type *void_type = objfile_type (ccp->of)->builtin_void;
-
-  if (ctf_func_info (ccp->fp, idx, &finfo) == CTF_ERR)
-    return nullptr;
-
-  argc = finfo.ctc_argc;
-  if (ctf_func_args (ccp->fp, idx, argc, argv) == CTF_ERR)
-    return nullptr;
-
-  gdb::unique_xmalloc_ptr<char> name (ctf_type_aname_raw (ccp->fp, idx));
-  if (name == nullptr)
-    return nullptr;
-
-  tid = ctf_lookup_by_symbol (ccp->fp, idx);
-  ftype = fetch_tid_type (ccp, tid);
-  if ((finfo.ctc_flags & CTF_FUNC_VARARG) != 0)
-    ftype->set_has_varargs (true);
-  ftype->set_num_fields (argc);
-
-  /* If argc is 0, it has a "void" type.  */
-  if (argc != 0)
-    ftype->set_fields
-      ((struct field *) TYPE_ZALLOC (ftype, argc * sizeof (struct field)));
-
-  /* TYPE_FIELD_TYPE must never be NULL.  Fill it with void_type, if failed
-     to find the argument type.  */
-  for (int iparam = 0; iparam < argc; iparam++)
-    {
-      atyp = fetch_tid_type (ccp, argv[iparam]);
-      if (atyp)
-	ftype->field (iparam).set_type (atyp);
-      else
-	ftype->field (iparam).set_type (void_type);
-    }
+  add_stt_entries (ccp, 0);
+}
 
-  sym = new_symbol (ccp, ftype, tid);
-  rettyp = fetch_tid_type (ccp, finfo.ctc_return);
-  if (rettyp != nullptr)
-    SYMBOL_TYPE (sym) = rettyp;
-  else
-    SYMBOL_TYPE (sym) = void_type;
+/* Add entries in function info section.  */
 
-  return sym;
+static void
+add_stt_func (struct ctf_context *ccp)
+{
+  add_stt_entries (ccp, 1);
 }
 
 /* Get text segment base for OBJFILE, TSIZE contains the segment size.  */
@@ -1317,12 +1294,71 @@ struct ctf_tid_and_type
 	       ctf_errmsg (ctf_errno (ccp->fp)));
 }
 
+/* Add entries in either data objects or function info section, controlled
+   by FUNCTIONS, to psymtab.  */
+
+static void
+ctf_psymtab_add_stt_entries (ctf_dict_t *cfp, ctf_psymtab *pst,
+			     struct objfile *of, int functions)
+{
+  ctf_next_t *i = nullptr;
+  ctf_id_t tid;
+  const char *tname;
+
+  while ((tid = ctf_symbol_next (cfp, &i, &tname, functions)) != CTF_ERR)
+    {
+      uint32_t kind = ctf_type_kind (cfp, tid);
+      address_class aclass;
+      domain_enum tdomain;
+      switch (kind)
+	{
+	  case CTF_K_STRUCT:
+	  case CTF_K_UNION:
+	  case CTF_K_ENUM:
+	    tdomain = STRUCT_DOMAIN;
+	    break;
+	  default:
+	    tdomain = VAR_DOMAIN;
+	    break;
+	}
+
+      if (kind == CTF_K_FUNCTION)
+	aclass = LOC_STATIC;
+      else if (kind == CTF_K_CONST)
+	aclass = LOC_CONST;
+      else
+	aclass = LOC_TYPEDEF;
+
+      pst->add_psymbol (tname, true,
+			tdomain, aclass, -1,
+			psymbol_placement::GLOBAL,
+			0, language_c, pst->context->partial_symtabs, of);
+    }
+}
+
+/* Add entries in data objects section to psymtab.  */
+
+static void
+ctf_psymtab_add_stt_obj (ctf_dict_t *cfp, ctf_psymtab *pst,
+			 struct objfile *of)
+{
+  ctf_psymtab_add_stt_entries (cfp, pst, of, 0);
+}
+
+/* Add entries in function info section to psymtab.  */
+
+static void
+ctf_psymtab_add_stt_func (ctf_dict_t *cfp, ctf_psymtab *pst,
+			  struct objfile *of)
+{
+  ctf_psymtab_add_stt_entries (cfp, pst, of, 1);
+}
+
 /* Read in full symbols for PST, and anything it depends on.  */
 
 void
 ctf_psymtab::expand_psymtab (struct objfile *objfile)
 {
-  struct symbol *sym;
   struct ctf_context *ccp;
 
   gdb_assert (!readin);
@@ -1341,21 +1377,8 @@ struct ctf_tid_and_type
 	       ctf_errmsg (ctf_errno (ccp->fp)));
 
   /* Add entries in data objects and function info sections.  */
-  for (unsigned long i = 0; ; i++)
-    {
-      sym = add_stt_obj (ccp, i);
-      if (sym == nullptr)
-	{
-	  if (ctf_errno (ccp->fp) == EINVAL
-	      || ctf_errno (ccp->fp) == ECTF_NOSYMTAB)
-	    break;
-	  sym = add_stt_func (ccp, i);
-	}
-      if (sym == nullptr)
-	continue;
-
-      set_symbol_address (ccp->of, sym, sym->linkage_name ());
-    }
+  add_stt_obj (ccp);
+  add_stt_func (ccp);
 
   readin = true;
 }
@@ -1409,6 +1432,7 @@ struct ctf_tid_and_type
 
 static ctf_psymtab *
 create_partial_symtab (const char *name,
+		       ctf_archive_t *arc,
 		       ctf_dict_t *cfp,
 		       psymtab_storage *partial_symtabs,
 		       struct objfile *objfile)
@@ -1419,11 +1443,12 @@ struct ctf_tid_and_type
   pst = new ctf_psymtab (name, partial_symtabs, objfile->per_bfd, 0);
 
   ccx = XOBNEW (&objfile->objfile_obstack, struct ctf_context);
+  ccx->arc = arc;
   ccx->fp = cfp;
+  ctf_ref (cfp);
   ccx->of = objfile;
   ccx->partial_symtabs = partial_symtabs;
   ccx->pst = pst;
-  ccx->builder = nullptr;
   pst->context = ccx;
 
   return pst;
@@ -1486,7 +1511,7 @@ struct ctf_tid_and_type
 
   ccp->pst->add_psymbol (name, false,
 			 domain, aclass, section,
-			 psymbol_placement::GLOBAL,
+			 psymbol_placement::STATIC,
 			 0, language_c, ccp->partial_symtabs, ccp->of);
 
   return 0;
@@ -1506,18 +1531,46 @@ struct ctf_tid_and_type
   return 0;
 }
 
+/* Start a subfile for CTF. FNAME is the name of the archive.  */
+
+static void
+ctf_start_archive (struct ctf_context *ccx, struct objfile *of,
+		   const char *fname)
+{
+  if (ccx->builder == nullptr)
+    {
+      ccx->builder = new buildsym_compunit (of,
+		      of->original_name, nullptr, language_c, 0);
+      ccx->builder->record_debugformat ("ctf");
+    }
+  ccx->builder->start_subfile (fname);
+}
+
 /* Setup partial_symtab's describing each source file for which
    debugging information is available.  */
 
 static void
 scan_partial_symbols (ctf_dict_t *cfp, psymtab_storage *partial_symtabs,
-		      struct objfile *of)
+		      struct ctf_per_tu_data *tup, const char *fname)
 {
-  bfd *abfd = of->obfd;
-  const char *name = bfd_get_filename (abfd);
-  ctf_psymtab *pst = create_partial_symtab (name, cfp, partial_symtabs, of);
+  struct objfile *of = tup->of;
+  bool isparent = false;
+
+  if (strcmp (fname, ".ctf") == 0)
+    {
+      fname = bfd_get_filename (of->obfd);
+      isparent = true;
+    }
+
+  ctf_psymtab *pst = create_partial_symtab (fname, tup->arc, cfp,
+					    partial_symtabs, of);
 
   struct ctf_context *ccx = pst->context;
+  if (isparent == false)
+    {
+      ctf_start_archive (ccx, of, fname);
+      ccx->pst = pst;
+    }
 
   if (ctf_type_iter (cfp, ctf_psymtab_type_cb, ccx) == CTF_ERR)
     complaint (_("ctf_type_iter scan_partial_symbols failed - %s"),
@@ -1530,46 +1583,33 @@ struct ctf_tid_and_type
   /* Scan CTF object and function sections which correspond to each
      STT_FUNC or STT_OBJECT entry in the symbol table,
      pick up what init_symtab has done.  */
-  for (unsigned long idx = 0; ; idx++)
-    {
-      ctf_id_t tid;
-      if ((tid = ctf_lookup_by_symbol (cfp, idx)) == CTF_ERR)
-	{
-	if (ctf_errno (cfp) == EINVAL || ctf_errno (cfp) == ECTF_NOSYMTAB)
-	  break;	// Done, reach end of the section.
-	else
-	  continue;
-	}
-      const char *tname = ctf_type_name_raw (cfp, tid);
-      uint32_t kind = ctf_type_kind (cfp, tid);
-      address_class aclass;
-      domain_enum tdomain;
-      switch (kind)
-	{
-	  case CTF_K_STRUCT:
-	  case CTF_K_UNION:
-	  case CTF_K_ENUM:
-	    tdomain = STRUCT_DOMAIN;
-	    break;
-	  default:
-	    tdomain = VAR_DOMAIN;
-	    break;
-	}
+  ctf_psymtab_add_stt_obj (cfp, pst, of);
+  ctf_psymtab_add_stt_func (cfp, pst, of);
 
-      if (kind == CTF_K_FUNCTION)
-	aclass = LOC_STATIC;
-      else if (kind == CTF_K_CONST)
-	aclass = LOC_CONST;
-      else
-	aclass = LOC_TYPEDEF;
+  pst->end ();
+}
 
-      pst->add_psymbol (tname, false,
-			tdomain, aclass, -1,
-			psymbol_placement::STATIC,
-			0, language_c, partial_symtabs, of);
+/* Callback to build the psymtab for archive member NAME.  */
+
+static int
+build_ctf_archive_member (ctf_dict_t *ctf, const char *name, void *arg)
+{
+  struct ctf_per_tu_data *tup = (struct ctf_per_tu_data *) arg;
+  ctf_dict_t *parent = tup->fp;
+
+  if (strcmp (name, ".ctf") != 0)
+    ctf_import (ctf, parent);
+
+  if (info_verbose)
+    {
+      printf_filtered (_("Scanning archive member %s..."), name);
+      gdb_flush (gdb_stdout);
     }
 
-  pst->end ();
+  psymtab_storage *pss = tup->psf->get_partial_symtabs ().get ();
+  scan_partial_symbols (ctf, pss, tup, name);
+
+  return 0;
 }
 
 /* Read CTF debugging information from a BFD section.  This is
@@ -1579,6 +1619,7 @@ struct ctf_tid_and_type
 void
 elfctf_build_psymtabs (struct objfile *of)
 {
+  struct ctf_per_tu_data pcu;
   bfd *abfd = of->obfd;
   int err;
 
@@ -1593,10 +1634,18 @@ struct ctf_tid_and_type
 	   bfd_get_filename (abfd), ctf_errmsg (err));
   ctf_dict_key.emplace (of, fp);
 
+  pcu.fp = fp;
+  pcu.of = of;
+  pcu.arc = arc;
+
   psymbol_functions *psf = new psymbol_functions ();
   psymtab_storage *partial_symtabs = psf->get_partial_symtabs ().get ();
   of->qf.emplace_front (psf);
-  scan_partial_symbols (fp, partial_symtabs, of);
+  pcu.psf = psf;
+
+  if (ctf_archive_iter (arc, build_ctf_archive_member, &pcu) < 0)
+    error (_("ctf_archive_iter failed in input file %s: - %s"),
+	   bfd_get_filename (abfd), ctf_errmsg (err));
 }
 
 #else
diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c
new file mode 100644
index 0000000..fe52b9e
--- /dev/null
+++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c
@@ -0,0 +1,18 @@
+struct A;
+struct B
+{
+  int foo;
+  struct A *bar;
+};
+
+struct A
+{
+  long a;
+  struct B *foo;
+};
+
+static struct A *foo __attribute__((used));
+
+int main()
+{
+}
diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c
new file mode 100644
index 0000000..aa2d177
--- /dev/null
+++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c
@@ -0,0 +1,16 @@
+struct B;
+struct A
+{
+  long a;
+  struct B *foo;
+  struct C *bar;
+};
+
+struct C
+{
+  struct B *foo;
+  int b;
+};
+
+static struct C *foo __attribute__((used));
+static struct A *bar __attribute__((used));
diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c
new file mode 100644
index 0000000..19947e8
--- /dev/null
+++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c
@@ -0,0 +1,3 @@
+struct A { struct B *foo; };
+static struct A *a __attribute__((__used__));
+static struct A *conflicty __attribute__((__used__));
diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c
new file mode 100644
index 0000000..6e0c957
--- /dev/null
+++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c
@@ -0,0 +1,4 @@
+struct A { struct B *foo; };
+struct B { struct B *next; };
+static struct A *a __attribute__((__used__));
+static struct B *conflicty __attribute__((__used__));
diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp b/gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp
new file mode 100644
index 0000000..b6e640e
--- /dev/null
+++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp
@@ -0,0 +1,43 @@
+# Copyright 2021 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file is a subset of ptype.exp written by Rob Savoye. (rob@cygnus.com)
+
+if [skip_ctf_tests] {
+    unsupported "no CTF debug format support, or CTF disabled in GDB"
+    return 0
+}
+
+standard_testfile cross-tu-cyclic-1.c  cross-tu-cyclic-2.c \
+	cross-tu-cyclic-3.c  cross-tu-cyclic-4.c
+
+# Using `-gt` generates full-fledged CTF debug information.
+set opts "additional_flags=-gt -Wl,--export-dynamic"
+if { [prepare_for_testing "failed to prepare" ${testfile} \
+	  [list $srcfile $srcfile2 $srcfile3 $srcfile4] \
+	  [list $opts nowarnings]] } {
+    return 0
+}
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+if [get_compiler_info] {
+    return -1
+}
+
+# Same thing with struct and union.
+gdb_test "ptype struct A" "type = struct A \{\[\r\n\]+\[ \t\]+struct B \\*foo;\[\r\n\]+\}.*" "ptype structure A"
+gdb_test "ptype struct B" "type = struct B \{\[\r\n\]+\[ \t\]+struct B \\*next;\[\r\n\]+\}.*" "ptype structure B"
+gdb_test "ptype struct C" "type = struct C \{\[\r\n\]+\[ \t\]+struct B \\*foo;\[\r\n\]+\[ \t\]+int b;\[\r\n\]+\}.*" "ptype structure C"
diff --git a/gdb/testsuite/gdb.ctf/ctf-a.c b/gdb/testsuite/gdb.ctf/ctf-a.c
new file mode 100644
index 0000000..9aa2a8f
--- /dev/null
+++ b/gdb/testsuite/gdb.ctf/ctf-a.c
@@ -0,0 +1,32 @@
+/* This test program is part of GDB, the GNU debugger.
+
+   Copyright 2021 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "ctf-a.h"
+
+static struct A a __attribute__((used));
+
+extern struct C *foo ();
+extern int bar ();
+
+int main ()
+{
+  struct C *cp;
+  cp = foo ();
+  if (cp)
+    return bar ();
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.ctf/ctf-a.h b/gdb/testsuite/gdb.ctf/ctf-a.h
new file mode 100644
index 0000000..297d740
--- /dev/null
+++ b/gdb/testsuite/gdb.ctf/ctf-a.h
@@ -0,0 +1,22 @@
+/* This test program is part of GDB, the GNU debugger.
+
+   Copyright 2021 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+struct A {
+  struct B *b;
+  struct A *next;
+};
+
diff --git a/gdb/testsuite/gdb.ctf/ctf-b.c b/gdb/testsuite/gdb.ctf/ctf-b.c
new file mode 100644
index 0000000..c3a8ce5
--- /dev/null
+++ b/gdb/testsuite/gdb.ctf/ctf-b.c
@@ -0,0 +1,25 @@
+/* This test program is part of GDB, the GNU debugger.
+
+   Copyright 2021 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "ctf-b.h"
+
+static struct B b __attribute__((used));
+
+int bar ()
+{
+  return b.wombat;
+}
diff --git a/gdb/testsuite/gdb.ctf/ctf-b.h b/gdb/testsuite/gdb.ctf/ctf-b.h
new file mode 100644
index 0000000..9dbdd7d
--- /dev/null
+++ b/gdb/testsuite/gdb.ctf/ctf-b.h
@@ -0,0 +1,22 @@
+/* This test program is part of GDB, the GNU debugger.
+
+   Copyright 2021 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+struct B {
+  struct C *c;
+  int wombat;
+};
+
diff --git a/gdb/testsuite/gdb.ctf/ctf-c.c b/gdb/testsuite/gdb.ctf/ctf-c.c
new file mode 100644
index 0000000..b4051b3
--- /dev/null
+++ b/gdb/testsuite/gdb.ctf/ctf-c.c
@@ -0,0 +1,25 @@
+/* This test program is part of GDB, the GNU debugger.
+
+   Copyright 2021 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "ctf-c.h"
+
+static struct C c __attribute__((used));
+
+struct C * foo ()
+{
+  return &c;
+}
diff --git a/gdb/testsuite/gdb.ctf/ctf-c.h b/gdb/testsuite/gdb.ctf/ctf-c.h
new file mode 100644
index 0000000..fb18157
--- /dev/null
+++ b/gdb/testsuite/gdb.ctf/ctf-c.h
@@ -0,0 +1,21 @@
+/* This test program is part of GDB, the GNU debugger.
+
+   Copyright 2021 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+struct C {
+  struct A *a;
+  int b;
+};
diff --git a/gdb/testsuite/gdb.ctf/multi.exp b/gdb/testsuite/gdb.ctf/multi.exp
new file mode 100644
index 0000000..973115e
--- /dev/null
+++ b/gdb/testsuite/gdb.ctf/multi.exp
@@ -0,0 +1,42 @@
+# Copyright 2021 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file is a subset of ptype.exp written by Rob Savoye. (rob@cygnus.com)
+
+if [skip_ctf_tests] {
+    unsupported "no CTF debug format support, or CTF disabled in GDB"
+    return 0
+}
+
+standard_testfile ctf-a.c ctf-b.c ctf-c.c
+
+# Using `-gt` generates full-fledged CTF debug information.
+set opts "additional_flags=-gt -Wl,--export-dynamic"
+if { [prepare_for_testing "failed to prepare" ${testfile} \
+	  [list $srcfile $srcfile2 $srcfile3] \
+	  [list $opts nowarnings]] } {
+    return 0
+}
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+if [get_compiler_info] {
+    return -1
+}
+
+# Same thing with struct and union.
+gdb_test "ptype struct A" "type = struct A \{\[\r\n\]+\[ \t\]+struct B \\*b;\[\r\n\]+\[ \t\]+struct A \\*next;\[\r\n\]+\}.*" "ptype structure A"
+gdb_test "ptype struct B" "type = struct B \{\[\r\n\]+\[ \t\]+struct C \\*c;\[\r\n\]+\[ \t\]+int \\wombat;\[\r\n\]+\}.*" "ptype structure B"
+gdb_test "ptype struct C" "type = struct C \{\[\r\n\]+\[ \t\]+struct A \\*a;\[\r\n\]+\[ \t\]+int b;\[\r\n\]+\}.*" "ptype structure C"
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PING][PATCH V5] CTF: multi-CU and archive support
  2021-05-18  0:20 [PATCH V5] CTF: multi-CU and archive support Weimin Pan
@ 2021-05-25  0:52 ` Wei-min Pan
  2021-06-02  0:05   ` [PING 2][PATCH " Wei-min Pan
  2021-06-10  0:40 ` [PATCH " Lancelot SIX
  2021-06-11 18:17 ` Tom Tromey
  2 siblings, 1 reply; 11+ messages in thread
From: Wei-min Pan @ 2021-05-25  0:52 UTC (permalink / raw)
  To: gdb-patches


On 5/17/2021 5:20 PM, Weimin Pan via Gdb-patches wrote:
> [Changes from V4:
>   - Treat CTF archives as CUs over dependencies to avoid over-expanding
>     psymtabs, as Tom Tromey pointed out.
>   - Avoid calling ctf_dict_close more than once on a dictionary.]
>
> Now gdb is capable of debugging executable, which consists of multiple
> compilation units (CUs) with the CTF debug info. An executable could
> potentially have one or more archives, which, in CTF context, contain
> conflicting types.
>
> all changes were made in ctfread.c in which elfctf_build_psymtabs was
> modified to handle archives, via the ctf archive iterator and its callback
> build_ctf_archive_member and scan_partial_symbols was modified to scan
> archives, which are treated as subfiles, to build the psymtabs.
>
> Also changes were made to handle CTF's data object section and function
> info section which now share the same format of their contents - an array
> of type IDs. New functions ctf_psymtab_add_stt_entries, which is called by
> ctf_psymtab_add_stt_obj and ctf_psymtab_add_stt_func, and add_stt_entries,
> which is called by add_stt_obj and add_stt_func when setting up psymtabs
> and full symtab, respectively.
> ---
>   gdb/ctfread.c                             | 311 +++++++++++++++++-------------
>   gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c |  18 ++
>   gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c |  16 ++
>   gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c |   3 +
>   gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c |   4 +
>   gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp |  43 +++++
>   gdb/testsuite/gdb.ctf/ctf-a.c             |  32 +++
>   gdb/testsuite/gdb.ctf/ctf-a.h             |  22 +++
>   gdb/testsuite/gdb.ctf/ctf-b.c             |  25 +++
>   gdb/testsuite/gdb.ctf/ctf-b.h             |  22 +++
>   gdb/testsuite/gdb.ctf/ctf-c.c             |  25 +++
>   gdb/testsuite/gdb.ctf/ctf-c.h             |  21 ++
>   gdb/testsuite/gdb.ctf/multi.exp           |  42 ++++
>   13 files changed, 453 insertions(+), 131 deletions(-)
>   create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c
>   create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c
>   create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c
>   create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c
>   create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp
>   create mode 100644 gdb/testsuite/gdb.ctf/ctf-a.c
>   create mode 100644 gdb/testsuite/gdb.ctf/ctf-a.h
>   create mode 100644 gdb/testsuite/gdb.ctf/ctf-b.c
>   create mode 100644 gdb/testsuite/gdb.ctf/ctf-b.h
>   create mode 100644 gdb/testsuite/gdb.ctf/ctf-c.c
>   create mode 100644 gdb/testsuite/gdb.ctf/ctf-c.h
>   create mode 100644 gdb/testsuite/gdb.ctf/multi.exp
>
> diff --git a/gdb/ctfread.c b/gdb/ctfread.c
> index 23e859a..1939f40 100644
> --- a/gdb/ctfread.c
> +++ b/gdb/ctfread.c
> @@ -117,6 +117,7 @@ struct ctf_context
>     struct objfile *of;
>     psymtab_storage *partial_symtabs;
>     partial_symtab *pst;
> +  ctf_archive_t *arc;
>     struct buildsym_compunit *builder;
>   };
>   
> @@ -166,6 +167,16 @@ struct ctf_field_info
>     std::vector<struct decl_field> nested_types_list;
>   };
>   
> +/* Data held for a translation unit.  */
> +
> +struct ctf_per_tu_data
> +{
> +  ctf_dict_t *fp;
> +  struct objfile *of;
> +  ctf_archive_t *arc;
> +  psymtab_storage *pss;
> +  psymbol_functions *psf;
> +};
>   
>   /* Local function prototypes */
>   
> @@ -245,10 +256,8 @@ struct ctf_tid_and_type
>     ids.tid = tid;
>     ids.type = typ;
>     slot = (struct ctf_tid_and_type **) htab_find_slot (htab, &ids, INSERT);
> -  if (*slot)
> -    complaint (_("An internal GDB problem: ctf_ id_t %ld type already set"),
> -	       (tid));
> -  *slot = XOBNEW (&of->objfile_obstack, struct ctf_tid_and_type);
> +  if (*slot == nullptr)
> +    *slot = XOBNEW (&of->objfile_obstack, struct ctf_tid_and_type);
>     **slot = ids;
>     return typ;
>   }
> @@ -510,7 +519,7 @@ struct ctf_tid_and_type
>   	    break;
>   	}
>   
> -      add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
> +      add_symbol_to_list (sym, ccp->builder->get_file_symbols ());
>       }
>   
>     return sym;
> @@ -1143,7 +1152,8 @@ struct ctf_tid_and_type
>   	if (type)
>   	  {
>   	    sym = new_symbol (ccp, type, id);
> -	    sym->compute_and_set_names (name, false, ccp->of->per_bfd);
> +	    if (sym)
> +	      sym->compute_and_set_names (name, false, ccp->of->per_bfd);
>   	  }
>   	break;
>         case CTF_K_STRUCT:
> @@ -1160,7 +1170,7 @@ struct ctf_tid_and_type
>   	SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
>   	SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT;
>   	sym->compute_and_set_names (name, false, ccp->of->per_bfd);
> -	add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
> +	add_symbol_to_list (sym, ccp->builder->get_file_symbols ());
>   	break;
>         default:
>   	complaint (_("ctf_add_var_cb: kind unsupported (%d)"), kind);
> @@ -1173,81 +1183,48 @@ struct ctf_tid_and_type
>     return 0;
>   }
>   
> -/* Add an ELF STT_OBJ symbol with index IDX to the symbol table.  */
> +/* Add entries in either data objects or function info section, controlled
> +   by FUNCTIONS.  */
>   
> -static struct symbol *
> -add_stt_obj (struct ctf_context *ccp, unsigned long idx)
> +static void
> +add_stt_entries (struct ctf_context *ccp, int functions)
>   {
> -  struct symbol *sym;
> -  struct type *type;
> +  ctf_next_t *i = nullptr;
> +  const char *tname;
>     ctf_id_t tid;
> +  struct symbol *sym = nullptr;
> +  struct type *type;
>   
> -  if ((tid = ctf_lookup_by_symbol (ccp->fp, idx)) == CTF_ERR)
> -    return nullptr;
> -
> -  type = fetch_tid_type (ccp, tid);
> -  if (type == nullptr)
> -    return nullptr;
> -
> -  sym = new_symbol (ccp, type, tid);
> -
> -  return sym;
> +  while ((tid = ctf_symbol_next (ccp->fp, &i, &tname, functions)) != CTF_ERR)
> +    {
> +      type = get_tid_type (ccp->of, tid);
> +      if (type == nullptr)
> +	continue;
> +      sym = new (&ccp->of->objfile_obstack) symbol;
> +      OBJSTAT (ccp->of, n_syms++);
> +      SYMBOL_TYPE (sym) = type;
> +      SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
> +      SYMBOL_ACLASS_INDEX (sym) = LOC_STATIC;
> +      sym->compute_and_set_names (tname, false, ccp->of->per_bfd);
> +      add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
> +      set_symbol_address (ccp->of, sym, tname);
> +    }
>   }
>   
> -/* Add an ELF STT_FUNC symbol with index IDX to the symbol table.  */
> +/* Add entries in data objects section.  */
>   
> -static struct symbol *
> -add_stt_func (struct ctf_context *ccp, unsigned long idx)
> +static void
> +add_stt_obj (struct ctf_context *ccp)
>   {
> -  struct type *ftype, *atyp, *rettyp;
> -  struct symbol *sym;
> -  ctf_funcinfo_t finfo;
> -  ctf_id_t argv[32];
> -  uint32_t argc;
> -  ctf_id_t tid;
> -  struct type *void_type = objfile_type (ccp->of)->builtin_void;
> -
> -  if (ctf_func_info (ccp->fp, idx, &finfo) == CTF_ERR)
> -    return nullptr;
> -
> -  argc = finfo.ctc_argc;
> -  if (ctf_func_args (ccp->fp, idx, argc, argv) == CTF_ERR)
> -    return nullptr;
> -
> -  gdb::unique_xmalloc_ptr<char> name (ctf_type_aname_raw (ccp->fp, idx));
> -  if (name == nullptr)
> -    return nullptr;
> -
> -  tid = ctf_lookup_by_symbol (ccp->fp, idx);
> -  ftype = fetch_tid_type (ccp, tid);
> -  if ((finfo.ctc_flags & CTF_FUNC_VARARG) != 0)
> -    ftype->set_has_varargs (true);
> -  ftype->set_num_fields (argc);
> -
> -  /* If argc is 0, it has a "void" type.  */
> -  if (argc != 0)
> -    ftype->set_fields
> -      ((struct field *) TYPE_ZALLOC (ftype, argc * sizeof (struct field)));
> -
> -  /* TYPE_FIELD_TYPE must never be NULL.  Fill it with void_type, if failed
> -     to find the argument type.  */
> -  for (int iparam = 0; iparam < argc; iparam++)
> -    {
> -      atyp = fetch_tid_type (ccp, argv[iparam]);
> -      if (atyp)
> -	ftype->field (iparam).set_type (atyp);
> -      else
> -	ftype->field (iparam).set_type (void_type);
> -    }
> +  add_stt_entries (ccp, 0);
> +}
>   
> -  sym = new_symbol (ccp, ftype, tid);
> -  rettyp = fetch_tid_type (ccp, finfo.ctc_return);
> -  if (rettyp != nullptr)
> -    SYMBOL_TYPE (sym) = rettyp;
> -  else
> -    SYMBOL_TYPE (sym) = void_type;
> +/* Add entries in function info section.  */
>   
> -  return sym;
> +static void
> +add_stt_func (struct ctf_context *ccp)
> +{
> +  add_stt_entries (ccp, 1);
>   }
>   
>   /* Get text segment base for OBJFILE, TSIZE contains the segment size.  */
> @@ -1317,12 +1294,71 @@ struct ctf_tid_and_type
>   	       ctf_errmsg (ctf_errno (ccp->fp)));
>   }
>   
> +/* Add entries in either data objects or function info section, controlled
> +   by FUNCTIONS, to psymtab.  */
> +
> +static void
> +ctf_psymtab_add_stt_entries (ctf_dict_t *cfp, ctf_psymtab *pst,
> +			     struct objfile *of, int functions)
> +{
> +  ctf_next_t *i = nullptr;
> +  ctf_id_t tid;
> +  const char *tname;
> +
> +  while ((tid = ctf_symbol_next (cfp, &i, &tname, functions)) != CTF_ERR)
> +    {
> +      uint32_t kind = ctf_type_kind (cfp, tid);
> +      address_class aclass;
> +      domain_enum tdomain;
> +      switch (kind)
> +	{
> +	  case CTF_K_STRUCT:
> +	  case CTF_K_UNION:
> +	  case CTF_K_ENUM:
> +	    tdomain = STRUCT_DOMAIN;
> +	    break;
> +	  default:
> +	    tdomain = VAR_DOMAIN;
> +	    break;
> +	}
> +
> +      if (kind == CTF_K_FUNCTION)
> +	aclass = LOC_STATIC;
> +      else if (kind == CTF_K_CONST)
> +	aclass = LOC_CONST;
> +      else
> +	aclass = LOC_TYPEDEF;
> +
> +      pst->add_psymbol (tname, true,
> +			tdomain, aclass, -1,
> +			psymbol_placement::GLOBAL,
> +			0, language_c, pst->context->partial_symtabs, of);
> +    }
> +}
> +
> +/* Add entries in data objects section to psymtab.  */
> +
> +static void
> +ctf_psymtab_add_stt_obj (ctf_dict_t *cfp, ctf_psymtab *pst,
> +			 struct objfile *of)
> +{
> +  ctf_psymtab_add_stt_entries (cfp, pst, of, 0);
> +}
> +
> +/* Add entries in function info section to psymtab.  */
> +
> +static void
> +ctf_psymtab_add_stt_func (ctf_dict_t *cfp, ctf_psymtab *pst,
> +			  struct objfile *of)
> +{
> +  ctf_psymtab_add_stt_entries (cfp, pst, of, 1);
> +}
> +
>   /* Read in full symbols for PST, and anything it depends on.  */
>   
>   void
>   ctf_psymtab::expand_psymtab (struct objfile *objfile)
>   {
> -  struct symbol *sym;
>     struct ctf_context *ccp;
>   
>     gdb_assert (!readin);
> @@ -1341,21 +1377,8 @@ struct ctf_tid_and_type
>   	       ctf_errmsg (ctf_errno (ccp->fp)));
>   
>     /* Add entries in data objects and function info sections.  */
> -  for (unsigned long i = 0; ; i++)
> -    {
> -      sym = add_stt_obj (ccp, i);
> -      if (sym == nullptr)
> -	{
> -	  if (ctf_errno (ccp->fp) == EINVAL
> -	      || ctf_errno (ccp->fp) == ECTF_NOSYMTAB)
> -	    break;
> -	  sym = add_stt_func (ccp, i);
> -	}
> -      if (sym == nullptr)
> -	continue;
> -
> -      set_symbol_address (ccp->of, sym, sym->linkage_name ());
> -    }
> +  add_stt_obj (ccp);
> +  add_stt_func (ccp);
>   
>     readin = true;
>   }
> @@ -1409,6 +1432,7 @@ struct ctf_tid_and_type
>   
>   static ctf_psymtab *
>   create_partial_symtab (const char *name,
> +		       ctf_archive_t *arc,
>   		       ctf_dict_t *cfp,
>   		       psymtab_storage *partial_symtabs,
>   		       struct objfile *objfile)
> @@ -1419,11 +1443,12 @@ struct ctf_tid_and_type
>     pst = new ctf_psymtab (name, partial_symtabs, objfile->per_bfd, 0);
>   
>     ccx = XOBNEW (&objfile->objfile_obstack, struct ctf_context);
> +  ccx->arc = arc;
>     ccx->fp = cfp;
> +  ctf_ref (cfp);
>     ccx->of = objfile;
>     ccx->partial_symtabs = partial_symtabs;
>     ccx->pst = pst;
> -  ccx->builder = nullptr;
>     pst->context = ccx;
>   
>     return pst;
> @@ -1486,7 +1511,7 @@ struct ctf_tid_and_type
>   
>     ccp->pst->add_psymbol (name, false,
>   			 domain, aclass, section,
> -			 psymbol_placement::GLOBAL,
> +			 psymbol_placement::STATIC,
>   			 0, language_c, ccp->partial_symtabs, ccp->of);
>   
>     return 0;
> @@ -1506,18 +1531,46 @@ struct ctf_tid_and_type
>     return 0;
>   }
>   
> +/* Start a subfile for CTF. FNAME is the name of the archive.  */
> +
> +static void
> +ctf_start_archive (struct ctf_context *ccx, struct objfile *of,
> +		   const char *fname)
> +{
> +  if (ccx->builder == nullptr)
> +    {
> +      ccx->builder = new buildsym_compunit (of,
> +		      of->original_name, nullptr, language_c, 0);
> +      ccx->builder->record_debugformat ("ctf");
> +    }
> +  ccx->builder->start_subfile (fname);
> +}
> +
>   /* Setup partial_symtab's describing each source file for which
>      debugging information is available.  */
>   
>   static void
>   scan_partial_symbols (ctf_dict_t *cfp, psymtab_storage *partial_symtabs,
> -		      struct objfile *of)
> +		      struct ctf_per_tu_data *tup, const char *fname)
>   {
> -  bfd *abfd = of->obfd;
> -  const char *name = bfd_get_filename (abfd);
> -  ctf_psymtab *pst = create_partial_symtab (name, cfp, partial_symtabs, of);
> +  struct objfile *of = tup->of;
> +  bool isparent = false;
> +
> +  if (strcmp (fname, ".ctf") == 0)
> +    {
> +      fname = bfd_get_filename (of->obfd);
> +      isparent = true;
> +    }
> +
> +  ctf_psymtab *pst = create_partial_symtab (fname, tup->arc, cfp,
> +					    partial_symtabs, of);
>   
>     struct ctf_context *ccx = pst->context;
> +  if (isparent == false)
> +    {
> +      ctf_start_archive (ccx, of, fname);
> +      ccx->pst = pst;
> +    }
>   
>     if (ctf_type_iter (cfp, ctf_psymtab_type_cb, ccx) == CTF_ERR)
>       complaint (_("ctf_type_iter scan_partial_symbols failed - %s"),
> @@ -1530,46 +1583,33 @@ struct ctf_tid_and_type
>     /* Scan CTF object and function sections which correspond to each
>        STT_FUNC or STT_OBJECT entry in the symbol table,
>        pick up what init_symtab has done.  */
> -  for (unsigned long idx = 0; ; idx++)
> -    {
> -      ctf_id_t tid;
> -      if ((tid = ctf_lookup_by_symbol (cfp, idx)) == CTF_ERR)
> -	{
> -	if (ctf_errno (cfp) == EINVAL || ctf_errno (cfp) == ECTF_NOSYMTAB)
> -	  break;	// Done, reach end of the section.
> -	else
> -	  continue;
> -	}
> -      const char *tname = ctf_type_name_raw (cfp, tid);
> -      uint32_t kind = ctf_type_kind (cfp, tid);
> -      address_class aclass;
> -      domain_enum tdomain;
> -      switch (kind)
> -	{
> -	  case CTF_K_STRUCT:
> -	  case CTF_K_UNION:
> -	  case CTF_K_ENUM:
> -	    tdomain = STRUCT_DOMAIN;
> -	    break;
> -	  default:
> -	    tdomain = VAR_DOMAIN;
> -	    break;
> -	}
> +  ctf_psymtab_add_stt_obj (cfp, pst, of);
> +  ctf_psymtab_add_stt_func (cfp, pst, of);
>   
> -      if (kind == CTF_K_FUNCTION)
> -	aclass = LOC_STATIC;
> -      else if (kind == CTF_K_CONST)
> -	aclass = LOC_CONST;
> -      else
> -	aclass = LOC_TYPEDEF;
> +  pst->end ();
> +}
>   
> -      pst->add_psymbol (tname, false,
> -			tdomain, aclass, -1,
> -			psymbol_placement::STATIC,
> -			0, language_c, partial_symtabs, of);
> +/* Callback to build the psymtab for archive member NAME.  */
> +
> +static int
> +build_ctf_archive_member (ctf_dict_t *ctf, const char *name, void *arg)
> +{
> +  struct ctf_per_tu_data *tup = (struct ctf_per_tu_data *) arg;
> +  ctf_dict_t *parent = tup->fp;
> +
> +  if (strcmp (name, ".ctf") != 0)
> +    ctf_import (ctf, parent);
> +
> +  if (info_verbose)
> +    {
> +      printf_filtered (_("Scanning archive member %s..."), name);
> +      gdb_flush (gdb_stdout);
>       }
>   
> -  pst->end ();
> +  psymtab_storage *pss = tup->psf->get_partial_symtabs ().get ();
> +  scan_partial_symbols (ctf, pss, tup, name);
> +
> +  return 0;
>   }
>   
>   /* Read CTF debugging information from a BFD section.  This is
> @@ -1579,6 +1619,7 @@ struct ctf_tid_and_type
>   void
>   elfctf_build_psymtabs (struct objfile *of)
>   {
> +  struct ctf_per_tu_data pcu;
>     bfd *abfd = of->obfd;
>     int err;
>   
> @@ -1593,10 +1634,18 @@ struct ctf_tid_and_type
>   	   bfd_get_filename (abfd), ctf_errmsg (err));
>     ctf_dict_key.emplace (of, fp);
>   
> +  pcu.fp = fp;
> +  pcu.of = of;
> +  pcu.arc = arc;
> +
>     psymbol_functions *psf = new psymbol_functions ();
>     psymtab_storage *partial_symtabs = psf->get_partial_symtabs ().get ();
>     of->qf.emplace_front (psf);
> -  scan_partial_symbols (fp, partial_symtabs, of);
> +  pcu.psf = psf;
> +
> +  if (ctf_archive_iter (arc, build_ctf_archive_member, &pcu) < 0)
> +    error (_("ctf_archive_iter failed in input file %s: - %s"),
> +	   bfd_get_filename (abfd), ctf_errmsg (err));
>   }
>   
>   #else
> diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c
> new file mode 100644
> index 0000000..fe52b9e
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c
> @@ -0,0 +1,18 @@
> +struct A;
> +struct B
> +{
> +  int foo;
> +  struct A *bar;
> +};
> +
> +struct A
> +{
> +  long a;
> +  struct B *foo;
> +};
> +
> +static struct A *foo __attribute__((used));
> +
> +int main()
> +{
> +}
> diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c
> new file mode 100644
> index 0000000..aa2d177
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c
> @@ -0,0 +1,16 @@
> +struct B;
> +struct A
> +{
> +  long a;
> +  struct B *foo;
> +  struct C *bar;
> +};
> +
> +struct C
> +{
> +  struct B *foo;
> +  int b;
> +};
> +
> +static struct C *foo __attribute__((used));
> +static struct A *bar __attribute__((used));
> diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c
> new file mode 100644
> index 0000000..19947e8
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c
> @@ -0,0 +1,3 @@
> +struct A { struct B *foo; };
> +static struct A *a __attribute__((__used__));
> +static struct A *conflicty __attribute__((__used__));
> diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c
> new file mode 100644
> index 0000000..6e0c957
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c
> @@ -0,0 +1,4 @@
> +struct A { struct B *foo; };
> +struct B { struct B *next; };
> +static struct A *a __attribute__((__used__));
> +static struct B *conflicty __attribute__((__used__));
> diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp b/gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp
> new file mode 100644
> index 0000000..b6e640e
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp
> @@ -0,0 +1,43 @@
> +# Copyright 2021 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!KfrttasFsnIw1ZHq2B1VVTIQZbEXNf8botBC8BmTRvyeUnbHs4wvBeakioqQKyuK$ >.
> +
> +# This file is a subset of ptype.exp written by Rob Savoye. (rob@cygnus.com)
> +
> +if [skip_ctf_tests] {
> +    unsupported "no CTF debug format support, or CTF disabled in GDB"
> +    return 0
> +}
> +
> +standard_testfile cross-tu-cyclic-1.c  cross-tu-cyclic-2.c \
> +	cross-tu-cyclic-3.c  cross-tu-cyclic-4.c
> +
> +# Using `-gt` generates full-fledged CTF debug information.
> +set opts "additional_flags=-gt -Wl,--export-dynamic"
> +if { [prepare_for_testing "failed to prepare" ${testfile} \
> +	  [list $srcfile $srcfile2 $srcfile3 $srcfile4] \
> +	  [list $opts nowarnings]] } {
> +    return 0
> +}
> +
> +# Create and source the file that provides information about the compiler
> +# used to compile the test case.
> +if [get_compiler_info] {
> +    return -1
> +}
> +
> +# Same thing with struct and union.
> +gdb_test "ptype struct A" "type = struct A \{\[\r\n\]+\[ \t\]+struct B \\*foo;\[\r\n\]+\}.*" "ptype structure A"
> +gdb_test "ptype struct B" "type = struct B \{\[\r\n\]+\[ \t\]+struct B \\*next;\[\r\n\]+\}.*" "ptype structure B"
> +gdb_test "ptype struct C" "type = struct C \{\[\r\n\]+\[ \t\]+struct B \\*foo;\[\r\n\]+\[ \t\]+int b;\[\r\n\]+\}.*" "ptype structure C"
> diff --git a/gdb/testsuite/gdb.ctf/ctf-a.c b/gdb/testsuite/gdb.ctf/ctf-a.c
> new file mode 100644
> index 0000000..9aa2a8f
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ctf/ctf-a.c
> @@ -0,0 +1,32 @@
> +/* This test program is part of GDB, the GNU debugger.
> +
> +   Copyright 2021 Free Software Foundation, Inc.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!KfrttasFsnIw1ZHq2B1VVTIQZbEXNf8botBC8BmTRvyeUnbHs4wvBeakioqQKyuK$ >.  */
> +
> +#include "ctf-a.h"
> +
> +static struct A a __attribute__((used));
> +
> +extern struct C *foo ();
> +extern int bar ();
> +
> +int main ()
> +{
> +  struct C *cp;
> +  cp = foo ();
> +  if (cp)
> +    return bar ();
> +  return 0;
> +}
> diff --git a/gdb/testsuite/gdb.ctf/ctf-a.h b/gdb/testsuite/gdb.ctf/ctf-a.h
> new file mode 100644
> index 0000000..297d740
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ctf/ctf-a.h
> @@ -0,0 +1,22 @@
> +/* This test program is part of GDB, the GNU debugger.
> +
> +   Copyright 2021 Free Software Foundation, Inc.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!KfrttasFsnIw1ZHq2B1VVTIQZbEXNf8botBC8BmTRvyeUnbHs4wvBeakioqQKyuK$ >.  */
> +
> +struct A {
> +  struct B *b;
> +  struct A *next;
> +};
> +
> diff --git a/gdb/testsuite/gdb.ctf/ctf-b.c b/gdb/testsuite/gdb.ctf/ctf-b.c
> new file mode 100644
> index 0000000..c3a8ce5
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ctf/ctf-b.c
> @@ -0,0 +1,25 @@
> +/* This test program is part of GDB, the GNU debugger.
> +
> +   Copyright 2021 Free Software Foundation, Inc.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!KfrttasFsnIw1ZHq2B1VVTIQZbEXNf8botBC8BmTRvyeUnbHs4wvBeakioqQKyuK$ >.  */
> +
> +#include "ctf-b.h"
> +
> +static struct B b __attribute__((used));
> +
> +int bar ()
> +{
> +  return b.wombat;
> +}
> diff --git a/gdb/testsuite/gdb.ctf/ctf-b.h b/gdb/testsuite/gdb.ctf/ctf-b.h
> new file mode 100644
> index 0000000..9dbdd7d
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ctf/ctf-b.h
> @@ -0,0 +1,22 @@
> +/* This test program is part of GDB, the GNU debugger.
> +
> +   Copyright 2021 Free Software Foundation, Inc.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!KfrttasFsnIw1ZHq2B1VVTIQZbEXNf8botBC8BmTRvyeUnbHs4wvBeakioqQKyuK$ >.  */
> +
> +struct B {
> +  struct C *c;
> +  int wombat;
> +};
> +
> diff --git a/gdb/testsuite/gdb.ctf/ctf-c.c b/gdb/testsuite/gdb.ctf/ctf-c.c
> new file mode 100644
> index 0000000..b4051b3
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ctf/ctf-c.c
> @@ -0,0 +1,25 @@
> +/* This test program is part of GDB, the GNU debugger.
> +
> +   Copyright 2021 Free Software Foundation, Inc.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!KfrttasFsnIw1ZHq2B1VVTIQZbEXNf8botBC8BmTRvyeUnbHs4wvBeakioqQKyuK$ >.  */
> +
> +#include "ctf-c.h"
> +
> +static struct C c __attribute__((used));
> +
> +struct C * foo ()
> +{
> +  return &c;
> +}
> diff --git a/gdb/testsuite/gdb.ctf/ctf-c.h b/gdb/testsuite/gdb.ctf/ctf-c.h
> new file mode 100644
> index 0000000..fb18157
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ctf/ctf-c.h
> @@ -0,0 +1,21 @@
> +/* This test program is part of GDB, the GNU debugger.
> +
> +   Copyright 2021 Free Software Foundation, Inc.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!KfrttasFsnIw1ZHq2B1VVTIQZbEXNf8botBC8BmTRvyeUnbHs4wvBeakioqQKyuK$ >.  */
> +
> +struct C {
> +  struct A *a;
> +  int b;
> +};
> diff --git a/gdb/testsuite/gdb.ctf/multi.exp b/gdb/testsuite/gdb.ctf/multi.exp
> new file mode 100644
> index 0000000..973115e
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ctf/multi.exp
> @@ -0,0 +1,42 @@
> +# Copyright 2021 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!KfrttasFsnIw1ZHq2B1VVTIQZbEXNf8botBC8BmTRvyeUnbHs4wvBeakioqQKyuK$ >.
> +
> +# This file is a subset of ptype.exp written by Rob Savoye. (rob@cygnus.com)
> +
> +if [skip_ctf_tests] {
> +    unsupported "no CTF debug format support, or CTF disabled in GDB"
> +    return 0
> +}
> +
> +standard_testfile ctf-a.c ctf-b.c ctf-c.c
> +
> +# Using `-gt` generates full-fledged CTF debug information.
> +set opts "additional_flags=-gt -Wl,--export-dynamic"
> +if { [prepare_for_testing "failed to prepare" ${testfile} \
> +	  [list $srcfile $srcfile2 $srcfile3] \
> +	  [list $opts nowarnings]] } {
> +    return 0
> +}
> +
> +# Create and source the file that provides information about the compiler
> +# used to compile the test case.
> +if [get_compiler_info] {
> +    return -1
> +}
> +
> +# Same thing with struct and union.
> +gdb_test "ptype struct A" "type = struct A \{\[\r\n\]+\[ \t\]+struct B \\*b;\[\r\n\]+\[ \t\]+struct A \\*next;\[\r\n\]+\}.*" "ptype structure A"
> +gdb_test "ptype struct B" "type = struct B \{\[\r\n\]+\[ \t\]+struct C \\*c;\[\r\n\]+\[ \t\]+int \\wombat;\[\r\n\]+\}.*" "ptype structure B"
> +gdb_test "ptype struct C" "type = struct C \{\[\r\n\]+\[ \t\]+struct A \\*a;\[\r\n\]+\[ \t\]+int b;\[\r\n\]+\}.*" "ptype structure C"

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PING 2][PATCH V5] CTF: multi-CU and archive support
  2021-05-25  0:52 ` [PING][PATCH " Wei-min Pan
@ 2021-06-02  0:05   ` Wei-min Pan
  2021-06-09  0:37     ` [PING 3][PATCH " Wei-min Pan
  0 siblings, 1 reply; 11+ messages in thread
From: Wei-min Pan @ 2021-06-02  0:05 UTC (permalink / raw)
  To: gdb-patches


On 5/24/2021 5:52 PM, Wei-min Pan wrote:
>
> On 5/17/2021 5:20 PM, Weimin Pan via Gdb-patches wrote:
>> [Changes from V4:
>>   - Treat CTF archives as CUs over dependencies to avoid over-expanding
>>     psymtabs, as Tom Tromey pointed out.
>>   - Avoid calling ctf_dict_close more than once on a dictionary.]
>>
>> Now gdb is capable of debugging executable, which consists of multiple
>> compilation units (CUs) with the CTF debug info. An executable could
>> potentially have one or more archives, which, in CTF context, contain
>> conflicting types.
>>
>> all changes were made in ctfread.c in which elfctf_build_psymtabs was
>> modified to handle archives, via the ctf archive iterator and its 
>> callback
>> build_ctf_archive_member and scan_partial_symbols was modified to scan
>> archives, which are treated as subfiles, to build the psymtabs.
>>
>> Also changes were made to handle CTF's data object section and function
>> info section which now share the same format of their contents - an 
>> array
>> of type IDs. New functions ctf_psymtab_add_stt_entries, which is 
>> called by
>> ctf_psymtab_add_stt_obj and ctf_psymtab_add_stt_func, and 
>> add_stt_entries,
>> which is called by add_stt_obj and add_stt_func when setting up psymtabs
>> and full symtab, respectively.
>> ---
>>   gdb/ctfread.c                             | 311 
>> +++++++++++++++++-------------
>>   gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c |  18 ++
>>   gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c |  16 ++
>>   gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c |   3 +
>>   gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c |   4 +
>>   gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp |  43 +++++
>>   gdb/testsuite/gdb.ctf/ctf-a.c             |  32 +++
>>   gdb/testsuite/gdb.ctf/ctf-a.h             |  22 +++
>>   gdb/testsuite/gdb.ctf/ctf-b.c             |  25 +++
>>   gdb/testsuite/gdb.ctf/ctf-b.h             |  22 +++
>>   gdb/testsuite/gdb.ctf/ctf-c.c             |  25 +++
>>   gdb/testsuite/gdb.ctf/ctf-c.h             |  21 ++
>>   gdb/testsuite/gdb.ctf/multi.exp           |  42 ++++
>>   13 files changed, 453 insertions(+), 131 deletions(-)
>>   create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c
>>   create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c
>>   create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c
>>   create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c
>>   create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp
>>   create mode 100644 gdb/testsuite/gdb.ctf/ctf-a.c
>>   create mode 100644 gdb/testsuite/gdb.ctf/ctf-a.h
>>   create mode 100644 gdb/testsuite/gdb.ctf/ctf-b.c
>>   create mode 100644 gdb/testsuite/gdb.ctf/ctf-b.h
>>   create mode 100644 gdb/testsuite/gdb.ctf/ctf-c.c
>>   create mode 100644 gdb/testsuite/gdb.ctf/ctf-c.h
>>   create mode 100644 gdb/testsuite/gdb.ctf/multi.exp
>>
>> diff --git a/gdb/ctfread.c b/gdb/ctfread.c
>> index 23e859a..1939f40 100644
>> --- a/gdb/ctfread.c
>> +++ b/gdb/ctfread.c
>> @@ -117,6 +117,7 @@ struct ctf_context
>>     struct objfile *of;
>>     psymtab_storage *partial_symtabs;
>>     partial_symtab *pst;
>> +  ctf_archive_t *arc;
>>     struct buildsym_compunit *builder;
>>   };
>>   @@ -166,6 +167,16 @@ struct ctf_field_info
>>     std::vector<struct decl_field> nested_types_list;
>>   };
>>   +/* Data held for a translation unit.  */
>> +
>> +struct ctf_per_tu_data
>> +{
>> +  ctf_dict_t *fp;
>> +  struct objfile *of;
>> +  ctf_archive_t *arc;
>> +  psymtab_storage *pss;
>> +  psymbol_functions *psf;
>> +};
>>     /* Local function prototypes */
>>   @@ -245,10 +256,8 @@ struct ctf_tid_and_type
>>     ids.tid = tid;
>>     ids.type = typ;
>>     slot = (struct ctf_tid_and_type **) htab_find_slot (htab, &ids, 
>> INSERT);
>> -  if (*slot)
>> -    complaint (_("An internal GDB problem: ctf_ id_t %ld type 
>> already set"),
>> -           (tid));
>> -  *slot = XOBNEW (&of->objfile_obstack, struct ctf_tid_and_type);
>> +  if (*slot == nullptr)
>> +    *slot = XOBNEW (&of->objfile_obstack, struct ctf_tid_and_type);
>>     **slot = ids;
>>     return typ;
>>   }
>> @@ -510,7 +519,7 @@ struct ctf_tid_and_type
>>           break;
>>       }
>>   -      add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
>> +      add_symbol_to_list (sym, ccp->builder->get_file_symbols ());
>>       }
>>       return sym;
>> @@ -1143,7 +1152,8 @@ struct ctf_tid_and_type
>>       if (type)
>>         {
>>           sym = new_symbol (ccp, type, id);
>> -        sym->compute_and_set_names (name, false, ccp->of->per_bfd);
>> +        if (sym)
>> +          sym->compute_and_set_names (name, false, ccp->of->per_bfd);
>>         }
>>       break;
>>         case CTF_K_STRUCT:
>> @@ -1160,7 +1170,7 @@ struct ctf_tid_and_type
>>       SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
>>       SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT;
>>       sym->compute_and_set_names (name, false, ccp->of->per_bfd);
>> -    add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
>> +    add_symbol_to_list (sym, ccp->builder->get_file_symbols ());
>>       break;
>>         default:
>>       complaint (_("ctf_add_var_cb: kind unsupported (%d)"), kind);
>> @@ -1173,81 +1183,48 @@ struct ctf_tid_and_type
>>     return 0;
>>   }
>>   -/* Add an ELF STT_OBJ symbol with index IDX to the symbol table.  */
>> +/* Add entries in either data objects or function info section, 
>> controlled
>> +   by FUNCTIONS.  */
>>   -static struct symbol *
>> -add_stt_obj (struct ctf_context *ccp, unsigned long idx)
>> +static void
>> +add_stt_entries (struct ctf_context *ccp, int functions)
>>   {
>> -  struct symbol *sym;
>> -  struct type *type;
>> +  ctf_next_t *i = nullptr;
>> +  const char *tname;
>>     ctf_id_t tid;
>> +  struct symbol *sym = nullptr;
>> +  struct type *type;
>>   -  if ((tid = ctf_lookup_by_symbol (ccp->fp, idx)) == CTF_ERR)
>> -    return nullptr;
>> -
>> -  type = fetch_tid_type (ccp, tid);
>> -  if (type == nullptr)
>> -    return nullptr;
>> -
>> -  sym = new_symbol (ccp, type, tid);
>> -
>> -  return sym;
>> +  while ((tid = ctf_symbol_next (ccp->fp, &i, &tname, functions)) != 
>> CTF_ERR)
>> +    {
>> +      type = get_tid_type (ccp->of, tid);
>> +      if (type == nullptr)
>> +    continue;
>> +      sym = new (&ccp->of->objfile_obstack) symbol;
>> +      OBJSTAT (ccp->of, n_syms++);
>> +      SYMBOL_TYPE (sym) = type;
>> +      SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
>> +      SYMBOL_ACLASS_INDEX (sym) = LOC_STATIC;
>> +      sym->compute_and_set_names (tname, false, ccp->of->per_bfd);
>> +      add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
>> +      set_symbol_address (ccp->of, sym, tname);
>> +    }
>>   }
>>   -/* Add an ELF STT_FUNC symbol with index IDX to the symbol table.  */
>> +/* Add entries in data objects section.  */
>>   -static struct symbol *
>> -add_stt_func (struct ctf_context *ccp, unsigned long idx)
>> +static void
>> +add_stt_obj (struct ctf_context *ccp)
>>   {
>> -  struct type *ftype, *atyp, *rettyp;
>> -  struct symbol *sym;
>> -  ctf_funcinfo_t finfo;
>> -  ctf_id_t argv[32];
>> -  uint32_t argc;
>> -  ctf_id_t tid;
>> -  struct type *void_type = objfile_type (ccp->of)->builtin_void;
>> -
>> -  if (ctf_func_info (ccp->fp, idx, &finfo) == CTF_ERR)
>> -    return nullptr;
>> -
>> -  argc = finfo.ctc_argc;
>> -  if (ctf_func_args (ccp->fp, idx, argc, argv) == CTF_ERR)
>> -    return nullptr;
>> -
>> -  gdb::unique_xmalloc_ptr<char> name (ctf_type_aname_raw (ccp->fp, 
>> idx));
>> -  if (name == nullptr)
>> -    return nullptr;
>> -
>> -  tid = ctf_lookup_by_symbol (ccp->fp, idx);
>> -  ftype = fetch_tid_type (ccp, tid);
>> -  if ((finfo.ctc_flags & CTF_FUNC_VARARG) != 0)
>> -    ftype->set_has_varargs (true);
>> -  ftype->set_num_fields (argc);
>> -
>> -  /* If argc is 0, it has a "void" type.  */
>> -  if (argc != 0)
>> -    ftype->set_fields
>> -      ((struct field *) TYPE_ZALLOC (ftype, argc * sizeof (struct 
>> field)));
>> -
>> -  /* TYPE_FIELD_TYPE must never be NULL.  Fill it with void_type, if 
>> failed
>> -     to find the argument type.  */
>> -  for (int iparam = 0; iparam < argc; iparam++)
>> -    {
>> -      atyp = fetch_tid_type (ccp, argv[iparam]);
>> -      if (atyp)
>> -    ftype->field (iparam).set_type (atyp);
>> -      else
>> -    ftype->field (iparam).set_type (void_type);
>> -    }
>> +  add_stt_entries (ccp, 0);
>> +}
>>   -  sym = new_symbol (ccp, ftype, tid);
>> -  rettyp = fetch_tid_type (ccp, finfo.ctc_return);
>> -  if (rettyp != nullptr)
>> -    SYMBOL_TYPE (sym) = rettyp;
>> -  else
>> -    SYMBOL_TYPE (sym) = void_type;
>> +/* Add entries in function info section.  */
>>   -  return sym;
>> +static void
>> +add_stt_func (struct ctf_context *ccp)
>> +{
>> +  add_stt_entries (ccp, 1);
>>   }
>>     /* Get text segment base for OBJFILE, TSIZE contains the segment 
>> size.  */
>> @@ -1317,12 +1294,71 @@ struct ctf_tid_and_type
>>              ctf_errmsg (ctf_errno (ccp->fp)));
>>   }
>>   +/* Add entries in either data objects or function info section, 
>> controlled
>> +   by FUNCTIONS, to psymtab.  */
>> +
>> +static void
>> +ctf_psymtab_add_stt_entries (ctf_dict_t *cfp, ctf_psymtab *pst,
>> +                 struct objfile *of, int functions)
>> +{
>> +  ctf_next_t *i = nullptr;
>> +  ctf_id_t tid;
>> +  const char *tname;
>> +
>> +  while ((tid = ctf_symbol_next (cfp, &i, &tname, functions)) != 
>> CTF_ERR)
>> +    {
>> +      uint32_t kind = ctf_type_kind (cfp, tid);
>> +      address_class aclass;
>> +      domain_enum tdomain;
>> +      switch (kind)
>> +    {
>> +      case CTF_K_STRUCT:
>> +      case CTF_K_UNION:
>> +      case CTF_K_ENUM:
>> +        tdomain = STRUCT_DOMAIN;
>> +        break;
>> +      default:
>> +        tdomain = VAR_DOMAIN;
>> +        break;
>> +    }
>> +
>> +      if (kind == CTF_K_FUNCTION)
>> +    aclass = LOC_STATIC;
>> +      else if (kind == CTF_K_CONST)
>> +    aclass = LOC_CONST;
>> +      else
>> +    aclass = LOC_TYPEDEF;
>> +
>> +      pst->add_psymbol (tname, true,
>> +            tdomain, aclass, -1,
>> +            psymbol_placement::GLOBAL,
>> +            0, language_c, pst->context->partial_symtabs, of);
>> +    }
>> +}
>> +
>> +/* Add entries in data objects section to psymtab.  */
>> +
>> +static void
>> +ctf_psymtab_add_stt_obj (ctf_dict_t *cfp, ctf_psymtab *pst,
>> +             struct objfile *of)
>> +{
>> +  ctf_psymtab_add_stt_entries (cfp, pst, of, 0);
>> +}
>> +
>> +/* Add entries in function info section to psymtab.  */
>> +
>> +static void
>> +ctf_psymtab_add_stt_func (ctf_dict_t *cfp, ctf_psymtab *pst,
>> +              struct objfile *of)
>> +{
>> +  ctf_psymtab_add_stt_entries (cfp, pst, of, 1);
>> +}
>> +
>>   /* Read in full symbols for PST, and anything it depends on. */
>>     void
>>   ctf_psymtab::expand_psymtab (struct objfile *objfile)
>>   {
>> -  struct symbol *sym;
>>     struct ctf_context *ccp;
>>       gdb_assert (!readin);
>> @@ -1341,21 +1377,8 @@ struct ctf_tid_and_type
>>              ctf_errmsg (ctf_errno (ccp->fp)));
>>       /* Add entries in data objects and function info sections.  */
>> -  for (unsigned long i = 0; ; i++)
>> -    {
>> -      sym = add_stt_obj (ccp, i);
>> -      if (sym == nullptr)
>> -    {
>> -      if (ctf_errno (ccp->fp) == EINVAL
>> -          || ctf_errno (ccp->fp) == ECTF_NOSYMTAB)
>> -        break;
>> -      sym = add_stt_func (ccp, i);
>> -    }
>> -      if (sym == nullptr)
>> -    continue;
>> -
>> -      set_symbol_address (ccp->of, sym, sym->linkage_name ());
>> -    }
>> +  add_stt_obj (ccp);
>> +  add_stt_func (ccp);
>>       readin = true;
>>   }
>> @@ -1409,6 +1432,7 @@ struct ctf_tid_and_type
>>     static ctf_psymtab *
>>   create_partial_symtab (const char *name,
>> +               ctf_archive_t *arc,
>>                  ctf_dict_t *cfp,
>>                  psymtab_storage *partial_symtabs,
>>                  struct objfile *objfile)
>> @@ -1419,11 +1443,12 @@ struct ctf_tid_and_type
>>     pst = new ctf_psymtab (name, partial_symtabs, objfile->per_bfd, 0);
>>       ccx = XOBNEW (&objfile->objfile_obstack, struct ctf_context);
>> +  ccx->arc = arc;
>>     ccx->fp = cfp;
>> +  ctf_ref (cfp);
>>     ccx->of = objfile;
>>     ccx->partial_symtabs = partial_symtabs;
>>     ccx->pst = pst;
>> -  ccx->builder = nullptr;
>>     pst->context = ccx;
>>       return pst;
>> @@ -1486,7 +1511,7 @@ struct ctf_tid_and_type
>>       ccp->pst->add_psymbol (name, false,
>>                domain, aclass, section,
>> -             psymbol_placement::GLOBAL,
>> +             psymbol_placement::STATIC,
>>                0, language_c, ccp->partial_symtabs, ccp->of);
>>       return 0;
>> @@ -1506,18 +1531,46 @@ struct ctf_tid_and_type
>>     return 0;
>>   }
>>   +/* Start a subfile for CTF. FNAME is the name of the archive.  */
>> +
>> +static void
>> +ctf_start_archive (struct ctf_context *ccx, struct objfile *of,
>> +           const char *fname)
>> +{
>> +  if (ccx->builder == nullptr)
>> +    {
>> +      ccx->builder = new buildsym_compunit (of,
>> +              of->original_name, nullptr, language_c, 0);
>> +      ccx->builder->record_debugformat ("ctf");
>> +    }
>> +  ccx->builder->start_subfile (fname);
>> +}
>> +
>>   /* Setup partial_symtab's describing each source file for which
>>      debugging information is available.  */
>>     static void
>>   scan_partial_symbols (ctf_dict_t *cfp, psymtab_storage 
>> *partial_symtabs,
>> -              struct objfile *of)
>> +              struct ctf_per_tu_data *tup, const char *fname)
>>   {
>> -  bfd *abfd = of->obfd;
>> -  const char *name = bfd_get_filename (abfd);
>> -  ctf_psymtab *pst = create_partial_symtab (name, cfp, 
>> partial_symtabs, of);
>> +  struct objfile *of = tup->of;
>> +  bool isparent = false;
>> +
>> +  if (strcmp (fname, ".ctf") == 0)
>> +    {
>> +      fname = bfd_get_filename (of->obfd);
>> +      isparent = true;
>> +    }
>> +
>> +  ctf_psymtab *pst = create_partial_symtab (fname, tup->arc, cfp,
>> +                        partial_symtabs, of);
>>       struct ctf_context *ccx = pst->context;
>> +  if (isparent == false)
>> +    {
>> +      ctf_start_archive (ccx, of, fname);
>> +      ccx->pst = pst;
>> +    }
>>       if (ctf_type_iter (cfp, ctf_psymtab_type_cb, ccx) == CTF_ERR)
>>       complaint (_("ctf_type_iter scan_partial_symbols failed - %s"),
>> @@ -1530,46 +1583,33 @@ struct ctf_tid_and_type
>>     /* Scan CTF object and function sections which correspond to each
>>        STT_FUNC or STT_OBJECT entry in the symbol table,
>>        pick up what init_symtab has done.  */
>> -  for (unsigned long idx = 0; ; idx++)
>> -    {
>> -      ctf_id_t tid;
>> -      if ((tid = ctf_lookup_by_symbol (cfp, idx)) == CTF_ERR)
>> -    {
>> -    if (ctf_errno (cfp) == EINVAL || ctf_errno (cfp) == ECTF_NOSYMTAB)
>> -      break;    // Done, reach end of the section.
>> -    else
>> -      continue;
>> -    }
>> -      const char *tname = ctf_type_name_raw (cfp, tid);
>> -      uint32_t kind = ctf_type_kind (cfp, tid);
>> -      address_class aclass;
>> -      domain_enum tdomain;
>> -      switch (kind)
>> -    {
>> -      case CTF_K_STRUCT:
>> -      case CTF_K_UNION:
>> -      case CTF_K_ENUM:
>> -        tdomain = STRUCT_DOMAIN;
>> -        break;
>> -      default:
>> -        tdomain = VAR_DOMAIN;
>> -        break;
>> -    }
>> +  ctf_psymtab_add_stt_obj (cfp, pst, of);
>> +  ctf_psymtab_add_stt_func (cfp, pst, of);
>>   -      if (kind == CTF_K_FUNCTION)
>> -    aclass = LOC_STATIC;
>> -      else if (kind == CTF_K_CONST)
>> -    aclass = LOC_CONST;
>> -      else
>> -    aclass = LOC_TYPEDEF;
>> +  pst->end ();
>> +}
>>   -      pst->add_psymbol (tname, false,
>> -            tdomain, aclass, -1,
>> -            psymbol_placement::STATIC,
>> -            0, language_c, partial_symtabs, of);
>> +/* Callback to build the psymtab for archive member NAME.  */
>> +
>> +static int
>> +build_ctf_archive_member (ctf_dict_t *ctf, const char *name, void *arg)
>> +{
>> +  struct ctf_per_tu_data *tup = (struct ctf_per_tu_data *) arg;
>> +  ctf_dict_t *parent = tup->fp;
>> +
>> +  if (strcmp (name, ".ctf") != 0)
>> +    ctf_import (ctf, parent);
>> +
>> +  if (info_verbose)
>> +    {
>> +      printf_filtered (_("Scanning archive member %s..."), name);
>> +      gdb_flush (gdb_stdout);
>>       }
>>   -  pst->end ();
>> +  psymtab_storage *pss = tup->psf->get_partial_symtabs ().get ();
>> +  scan_partial_symbols (ctf, pss, tup, name);
>> +
>> +  return 0;
>>   }
>>     /* Read CTF debugging information from a BFD section.  This is
>> @@ -1579,6 +1619,7 @@ struct ctf_tid_and_type
>>   void
>>   elfctf_build_psymtabs (struct objfile *of)
>>   {
>> +  struct ctf_per_tu_data pcu;
>>     bfd *abfd = of->obfd;
>>     int err;
>>   @@ -1593,10 +1634,18 @@ struct ctf_tid_and_type
>>          bfd_get_filename (abfd), ctf_errmsg (err));
>>     ctf_dict_key.emplace (of, fp);
>>   +  pcu.fp = fp;
>> +  pcu.of = of;
>> +  pcu.arc = arc;
>> +
>>     psymbol_functions *psf = new psymbol_functions ();
>>     psymtab_storage *partial_symtabs = psf->get_partial_symtabs 
>> ().get ();
>>     of->qf.emplace_front (psf);
>> -  scan_partial_symbols (fp, partial_symtabs, of);
>> +  pcu.psf = psf;
>> +
>> +  if (ctf_archive_iter (arc, build_ctf_archive_member, &pcu) < 0)
>> +    error (_("ctf_archive_iter failed in input file %s: - %s"),
>> +       bfd_get_filename (abfd), ctf_errmsg (err));
>>   }
>>     #else
>> diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c 
>> b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c
>> new file mode 100644
>> index 0000000..fe52b9e
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c
>> @@ -0,0 +1,18 @@
>> +struct A;
>> +struct B
>> +{
>> +  int foo;
>> +  struct A *bar;
>> +};
>> +
>> +struct A
>> +{
>> +  long a;
>> +  struct B *foo;
>> +};
>> +
>> +static struct A *foo __attribute__((used));
>> +
>> +int main()
>> +{
>> +}
>> diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c 
>> b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c
>> new file mode 100644
>> index 0000000..aa2d177
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c
>> @@ -0,0 +1,16 @@
>> +struct B;
>> +struct A
>> +{
>> +  long a;
>> +  struct B *foo;
>> +  struct C *bar;
>> +};
>> +
>> +struct C
>> +{
>> +  struct B *foo;
>> +  int b;
>> +};
>> +
>> +static struct C *foo __attribute__((used));
>> +static struct A *bar __attribute__((used));
>> diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c 
>> b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c
>> new file mode 100644
>> index 0000000..19947e8
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c
>> @@ -0,0 +1,3 @@
>> +struct A { struct B *foo; };
>> +static struct A *a __attribute__((__used__));
>> +static struct A *conflicty __attribute__((__used__));
>> diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c 
>> b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c
>> new file mode 100644
>> index 0000000..6e0c957
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c
>> @@ -0,0 +1,4 @@
>> +struct A { struct B *foo; };
>> +struct B { struct B *next; };
>> +static struct A *a __attribute__((__used__));
>> +static struct B *conflicty __attribute__((__used__));
>> diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp 
>> b/gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp
>> new file mode 100644
>> index 0000000..b6e640e
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp
>> @@ -0,0 +1,43 @@
>> +# Copyright 2021 Free Software Foundation, Inc.
>> +
>> +# This program is free software; you can redistribute it and/or modify
>> +# it under the terms of the GNU General Public License as published by
>> +# the Free Software Foundation; either version 3 of the License, or
>> +# (at your option) any later version.
>> +#
>> +# This program is distributed in the hope that it will be useful,
>> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> +# GNU General Public License for more details.
>> +#
>> +# You should have received a copy of the GNU General Public License
>> +# along with this program.  If not, see 
>> <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!KfrttasFsnIw1ZHq2B1VVTIQZbEXNf8botBC8BmTRvyeUnbHs4wvBeakioqQKyuK$ 
>> >.
>> +
>> +# This file is a subset of ptype.exp written by Rob Savoye. 
>> (rob@cygnus.com)
>> +
>> +if [skip_ctf_tests] {
>> +    unsupported "no CTF debug format support, or CTF disabled in GDB"
>> +    return 0
>> +}
>> +
>> +standard_testfile cross-tu-cyclic-1.c  cross-tu-cyclic-2.c \
>> +    cross-tu-cyclic-3.c  cross-tu-cyclic-4.c
>> +
>> +# Using `-gt` generates full-fledged CTF debug information.
>> +set opts "additional_flags=-gt -Wl,--export-dynamic"
>> +if { [prepare_for_testing "failed to prepare" ${testfile} \
>> +      [list $srcfile $srcfile2 $srcfile3 $srcfile4] \
>> +      [list $opts nowarnings]] } {
>> +    return 0
>> +}
>> +
>> +# Create and source the file that provides information about the 
>> compiler
>> +# used to compile the test case.
>> +if [get_compiler_info] {
>> +    return -1
>> +}
>> +
>> +# Same thing with struct and union.
>> +gdb_test "ptype struct A" "type = struct A \{\[\r\n\]+\[ \t\]+struct 
>> B \\*foo;\[\r\n\]+\}.*" "ptype structure A"
>> +gdb_test "ptype struct B" "type = struct B \{\[\r\n\]+\[ \t\]+struct 
>> B \\*next;\[\r\n\]+\}.*" "ptype structure B"
>> +gdb_test "ptype struct C" "type = struct C \{\[\r\n\]+\[ \t\]+struct 
>> B \\*foo;\[\r\n\]+\[ \t\]+int b;\[\r\n\]+\}.*" "ptype structure C"
>> diff --git a/gdb/testsuite/gdb.ctf/ctf-a.c 
>> b/gdb/testsuite/gdb.ctf/ctf-a.c
>> new file mode 100644
>> index 0000000..9aa2a8f
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.ctf/ctf-a.c
>> @@ -0,0 +1,32 @@
>> +/* This test program is part of GDB, the GNU debugger.
>> +
>> +   Copyright 2021 Free Software Foundation, Inc.
>> +
>> +   This program is free software; you can redistribute it and/or modify
>> +   it under the terms of the GNU General Public License as published by
>> +   the Free Software Foundation; either version 3 of the License, or
>> +   (at your option) any later version.
>> +
>> +   This program is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> +   GNU General Public License for more details.
>> +
>> +   You should have received a copy of the GNU General Public License
>> +   along with this program.  If not, see 
>> <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!KfrttasFsnIw1ZHq2B1VVTIQZbEXNf8botBC8BmTRvyeUnbHs4wvBeakioqQKyuK$ 
>> >.  */
>> +
>> +#include "ctf-a.h"
>> +
>> +static struct A a __attribute__((used));
>> +
>> +extern struct C *foo ();
>> +extern int bar ();
>> +
>> +int main ()
>> +{
>> +  struct C *cp;
>> +  cp = foo ();
>> +  if (cp)
>> +    return bar ();
>> +  return 0;
>> +}
>> diff --git a/gdb/testsuite/gdb.ctf/ctf-a.h 
>> b/gdb/testsuite/gdb.ctf/ctf-a.h
>> new file mode 100644
>> index 0000000..297d740
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.ctf/ctf-a.h
>> @@ -0,0 +1,22 @@
>> +/* This test program is part of GDB, the GNU debugger.
>> +
>> +   Copyright 2021 Free Software Foundation, Inc.
>> +
>> +   This program is free software; you can redistribute it and/or modify
>> +   it under the terms of the GNU General Public License as published by
>> +   the Free Software Foundation; either version 3 of the License, or
>> +   (at your option) any later version.
>> +
>> +   This program is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> +   GNU General Public License for more details.
>> +
>> +   You should have received a copy of the GNU General Public License
>> +   along with this program.  If not, see 
>> <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!KfrttasFsnIw1ZHq2B1VVTIQZbEXNf8botBC8BmTRvyeUnbHs4wvBeakioqQKyuK$ 
>> >.  */
>> +
>> +struct A {
>> +  struct B *b;
>> +  struct A *next;
>> +};
>> +
>> diff --git a/gdb/testsuite/gdb.ctf/ctf-b.c 
>> b/gdb/testsuite/gdb.ctf/ctf-b.c
>> new file mode 100644
>> index 0000000..c3a8ce5
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.ctf/ctf-b.c
>> @@ -0,0 +1,25 @@
>> +/* This test program is part of GDB, the GNU debugger.
>> +
>> +   Copyright 2021 Free Software Foundation, Inc.
>> +
>> +   This program is free software; you can redistribute it and/or modify
>> +   it under the terms of the GNU General Public License as published by
>> +   the Free Software Foundation; either version 3 of the License, or
>> +   (at your option) any later version.
>> +
>> +   This program is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> +   GNU General Public License for more details.
>> +
>> +   You should have received a copy of the GNU General Public License
>> +   along with this program.  If not, see 
>> <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!KfrttasFsnIw1ZHq2B1VVTIQZbEXNf8botBC8BmTRvyeUnbHs4wvBeakioqQKyuK$ 
>> >.  */
>> +
>> +#include "ctf-b.h"
>> +
>> +static struct B b __attribute__((used));
>> +
>> +int bar ()
>> +{
>> +  return b.wombat;
>> +}
>> diff --git a/gdb/testsuite/gdb.ctf/ctf-b.h 
>> b/gdb/testsuite/gdb.ctf/ctf-b.h
>> new file mode 100644
>> index 0000000..9dbdd7d
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.ctf/ctf-b.h
>> @@ -0,0 +1,22 @@
>> +/* This test program is part of GDB, the GNU debugger.
>> +
>> +   Copyright 2021 Free Software Foundation, Inc.
>> +
>> +   This program is free software; you can redistribute it and/or modify
>> +   it under the terms of the GNU General Public License as published by
>> +   the Free Software Foundation; either version 3 of the License, or
>> +   (at your option) any later version.
>> +
>> +   This program is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> +   GNU General Public License for more details.
>> +
>> +   You should have received a copy of the GNU General Public License
>> +   along with this program.  If not, see 
>> <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!KfrttasFsnIw1ZHq2B1VVTIQZbEXNf8botBC8BmTRvyeUnbHs4wvBeakioqQKyuK$ 
>> >.  */
>> +
>> +struct B {
>> +  struct C *c;
>> +  int wombat;
>> +};
>> +
>> diff --git a/gdb/testsuite/gdb.ctf/ctf-c.c 
>> b/gdb/testsuite/gdb.ctf/ctf-c.c
>> new file mode 100644
>> index 0000000..b4051b3
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.ctf/ctf-c.c
>> @@ -0,0 +1,25 @@
>> +/* This test program is part of GDB, the GNU debugger.
>> +
>> +   Copyright 2021 Free Software Foundation, Inc.
>> +
>> +   This program is free software; you can redistribute it and/or modify
>> +   it under the terms of the GNU General Public License as published by
>> +   the Free Software Foundation; either version 3 of the License, or
>> +   (at your option) any later version.
>> +
>> +   This program is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> +   GNU General Public License for more details.
>> +
>> +   You should have received a copy of the GNU General Public License
>> +   along with this program.  If not, see 
>> <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!KfrttasFsnIw1ZHq2B1VVTIQZbEXNf8botBC8BmTRvyeUnbHs4wvBeakioqQKyuK$ 
>> >.  */
>> +
>> +#include "ctf-c.h"
>> +
>> +static struct C c __attribute__((used));
>> +
>> +struct C * foo ()
>> +{
>> +  return &c;
>> +}
>> diff --git a/gdb/testsuite/gdb.ctf/ctf-c.h 
>> b/gdb/testsuite/gdb.ctf/ctf-c.h
>> new file mode 100644
>> index 0000000..fb18157
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.ctf/ctf-c.h
>> @@ -0,0 +1,21 @@
>> +/* This test program is part of GDB, the GNU debugger.
>> +
>> +   Copyright 2021 Free Software Foundation, Inc.
>> +
>> +   This program is free software; you can redistribute it and/or modify
>> +   it under the terms of the GNU General Public License as published by
>> +   the Free Software Foundation; either version 3 of the License, or
>> +   (at your option) any later version.
>> +
>> +   This program is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> +   GNU General Public License for more details.
>> +
>> +   You should have received a copy of the GNU General Public License
>> +   along with this program.  If not, see 
>> <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!KfrttasFsnIw1ZHq2B1VVTIQZbEXNf8botBC8BmTRvyeUnbHs4wvBeakioqQKyuK$ 
>> >.  */
>> +
>> +struct C {
>> +  struct A *a;
>> +  int b;
>> +};
>> diff --git a/gdb/testsuite/gdb.ctf/multi.exp 
>> b/gdb/testsuite/gdb.ctf/multi.exp
>> new file mode 100644
>> index 0000000..973115e
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.ctf/multi.exp
>> @@ -0,0 +1,42 @@
>> +# Copyright 2021 Free Software Foundation, Inc.
>> +
>> +# This program is free software; you can redistribute it and/or modify
>> +# it under the terms of the GNU General Public License as published by
>> +# the Free Software Foundation; either version 3 of the License, or
>> +# (at your option) any later version.
>> +#
>> +# This program is distributed in the hope that it will be useful,
>> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> +# GNU General Public License for more details.
>> +#
>> +# You should have received a copy of the GNU General Public License
>> +# along with this program.  If not, see 
>> <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!KfrttasFsnIw1ZHq2B1VVTIQZbEXNf8botBC8BmTRvyeUnbHs4wvBeakioqQKyuK$ 
>> >.
>> +
>> +# This file is a subset of ptype.exp written by Rob Savoye. 
>> (rob@cygnus.com)
>> +
>> +if [skip_ctf_tests] {
>> +    unsupported "no CTF debug format support, or CTF disabled in GDB"
>> +    return 0
>> +}
>> +
>> +standard_testfile ctf-a.c ctf-b.c ctf-c.c
>> +
>> +# Using `-gt` generates full-fledged CTF debug information.
>> +set opts "additional_flags=-gt -Wl,--export-dynamic"
>> +if { [prepare_for_testing "failed to prepare" ${testfile} \
>> +      [list $srcfile $srcfile2 $srcfile3] \
>> +      [list $opts nowarnings]] } {
>> +    return 0
>> +}
>> +
>> +# Create and source the file that provides information about the 
>> compiler
>> +# used to compile the test case.
>> +if [get_compiler_info] {
>> +    return -1
>> +}
>> +
>> +# Same thing with struct and union.
>> +gdb_test "ptype struct A" "type = struct A \{\[\r\n\]+\[ \t\]+struct 
>> B \\*b;\[\r\n\]+\[ \t\]+struct A \\*next;\[\r\n\]+\}.*" "ptype 
>> structure A"
>> +gdb_test "ptype struct B" "type = struct B \{\[\r\n\]+\[ \t\]+struct 
>> C \\*c;\[\r\n\]+\[ \t\]+int \\wombat;\[\r\n\]+\}.*" "ptype structure B"
>> +gdb_test "ptype struct C" "type = struct C \{\[\r\n\]+\[ \t\]+struct 
>> A \\*a;\[\r\n\]+\[ \t\]+int b;\[\r\n\]+\}.*" "ptype structure C"

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PING 3][PATCH V5] CTF: multi-CU and archive support
  2021-06-02  0:05   ` [PING 2][PATCH " Wei-min Pan
@ 2021-06-09  0:37     ` Wei-min Pan
  0 siblings, 0 replies; 11+ messages in thread
From: Wei-min Pan @ 2021-06-09  0:37 UTC (permalink / raw)
  To: gdb-patches


On 6/1/2021 5:05 PM, Wei-min Pan via Gdb-patches wrote:
>
> On 5/24/2021 5:52 PM, Wei-min Pan wrote:
>>
>> On 5/17/2021 5:20 PM, Weimin Pan via Gdb-patches wrote:
>>> [Changes from V4:
>>>   - Treat CTF archives as CUs over dependencies to avoid over-expanding
>>>     psymtabs, as Tom Tromey pointed out.
>>>   - Avoid calling ctf_dict_close more than once on a dictionary.]
>>>
>>> Now gdb is capable of debugging executable, which consists of multiple
>>> compilation units (CUs) with the CTF debug info. An executable could
>>> potentially have one or more archives, which, in CTF context, contain
>>> conflicting types.
>>>
>>> all changes were made in ctfread.c in which elfctf_build_psymtabs was
>>> modified to handle archives, via the ctf archive iterator and its 
>>> callback
>>> build_ctf_archive_member and scan_partial_symbols was modified to scan
>>> archives, which are treated as subfiles, to build the psymtabs.
>>>
>>> Also changes were made to handle CTF's data object section and function
>>> info section which now share the same format of their contents - an 
>>> array
>>> of type IDs. New functions ctf_psymtab_add_stt_entries, which is 
>>> called by
>>> ctf_psymtab_add_stt_obj and ctf_psymtab_add_stt_func, and 
>>> add_stt_entries,
>>> which is called by add_stt_obj and add_stt_func when setting up 
>>> psymtabs
>>> and full symtab, respectively.
>>> ---
>>>   gdb/ctfread.c                             | 311 
>>> +++++++++++++++++-------------
>>>   gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c |  18 ++
>>>   gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c |  16 ++
>>>   gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c |   3 +
>>>   gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c |   4 +
>>>   gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp |  43 +++++
>>>   gdb/testsuite/gdb.ctf/ctf-a.c             |  32 +++
>>>   gdb/testsuite/gdb.ctf/ctf-a.h             |  22 +++
>>>   gdb/testsuite/gdb.ctf/ctf-b.c             |  25 +++
>>>   gdb/testsuite/gdb.ctf/ctf-b.h             |  22 +++
>>>   gdb/testsuite/gdb.ctf/ctf-c.c             |  25 +++
>>>   gdb/testsuite/gdb.ctf/ctf-c.h             |  21 ++
>>>   gdb/testsuite/gdb.ctf/multi.exp           |  42 ++++
>>>   13 files changed, 453 insertions(+), 131 deletions(-)
>>>   create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c
>>>   create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c
>>>   create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c
>>>   create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c
>>>   create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp
>>>   create mode 100644 gdb/testsuite/gdb.ctf/ctf-a.c
>>>   create mode 100644 gdb/testsuite/gdb.ctf/ctf-a.h
>>>   create mode 100644 gdb/testsuite/gdb.ctf/ctf-b.c
>>>   create mode 100644 gdb/testsuite/gdb.ctf/ctf-b.h
>>>   create mode 100644 gdb/testsuite/gdb.ctf/ctf-c.c
>>>   create mode 100644 gdb/testsuite/gdb.ctf/ctf-c.h
>>>   create mode 100644 gdb/testsuite/gdb.ctf/multi.exp
>>>
>>> diff --git a/gdb/ctfread.c b/gdb/ctfread.c
>>> index 23e859a..1939f40 100644
>>> --- a/gdb/ctfread.c
>>> +++ b/gdb/ctfread.c
>>> @@ -117,6 +117,7 @@ struct ctf_context
>>>     struct objfile *of;
>>>     psymtab_storage *partial_symtabs;
>>>     partial_symtab *pst;
>>> +  ctf_archive_t *arc;
>>>     struct buildsym_compunit *builder;
>>>   };
>>>   @@ -166,6 +167,16 @@ struct ctf_field_info
>>>     std::vector<struct decl_field> nested_types_list;
>>>   };
>>>   +/* Data held for a translation unit.  */
>>> +
>>> +struct ctf_per_tu_data
>>> +{
>>> +  ctf_dict_t *fp;
>>> +  struct objfile *of;
>>> +  ctf_archive_t *arc;
>>> +  psymtab_storage *pss;
>>> +  psymbol_functions *psf;
>>> +};
>>>     /* Local function prototypes */
>>>   @@ -245,10 +256,8 @@ struct ctf_tid_and_type
>>>     ids.tid = tid;
>>>     ids.type = typ;
>>>     slot = (struct ctf_tid_and_type **) htab_find_slot (htab, &ids, 
>>> INSERT);
>>> -  if (*slot)
>>> -    complaint (_("An internal GDB problem: ctf_ id_t %ld type 
>>> already set"),
>>> -           (tid));
>>> -  *slot = XOBNEW (&of->objfile_obstack, struct ctf_tid_and_type);
>>> +  if (*slot == nullptr)
>>> +    *slot = XOBNEW (&of->objfile_obstack, struct ctf_tid_and_type);
>>>     **slot = ids;
>>>     return typ;
>>>   }
>>> @@ -510,7 +519,7 @@ struct ctf_tid_and_type
>>>           break;
>>>       }
>>>   -      add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
>>> +      add_symbol_to_list (sym, ccp->builder->get_file_symbols ());
>>>       }
>>>       return sym;
>>> @@ -1143,7 +1152,8 @@ struct ctf_tid_and_type
>>>       if (type)
>>>         {
>>>           sym = new_symbol (ccp, type, id);
>>> -        sym->compute_and_set_names (name, false, ccp->of->per_bfd);
>>> +        if (sym)
>>> +          sym->compute_and_set_names (name, false, ccp->of->per_bfd);
>>>         }
>>>       break;
>>>         case CTF_K_STRUCT:
>>> @@ -1160,7 +1170,7 @@ struct ctf_tid_and_type
>>>       SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
>>>       SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT;
>>>       sym->compute_and_set_names (name, false, ccp->of->per_bfd);
>>> -    add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
>>> +    add_symbol_to_list (sym, ccp->builder->get_file_symbols ());
>>>       break;
>>>         default:
>>>       complaint (_("ctf_add_var_cb: kind unsupported (%d)"), kind);
>>> @@ -1173,81 +1183,48 @@ struct ctf_tid_and_type
>>>     return 0;
>>>   }
>>>   -/* Add an ELF STT_OBJ symbol with index IDX to the symbol table.  */
>>> +/* Add entries in either data objects or function info section, 
>>> controlled
>>> +   by FUNCTIONS.  */
>>>   -static struct symbol *
>>> -add_stt_obj (struct ctf_context *ccp, unsigned long idx)
>>> +static void
>>> +add_stt_entries (struct ctf_context *ccp, int functions)
>>>   {
>>> -  struct symbol *sym;
>>> -  struct type *type;
>>> +  ctf_next_t *i = nullptr;
>>> +  const char *tname;
>>>     ctf_id_t tid;
>>> +  struct symbol *sym = nullptr;
>>> +  struct type *type;
>>>   -  if ((tid = ctf_lookup_by_symbol (ccp->fp, idx)) == CTF_ERR)
>>> -    return nullptr;
>>> -
>>> -  type = fetch_tid_type (ccp, tid);
>>> -  if (type == nullptr)
>>> -    return nullptr;
>>> -
>>> -  sym = new_symbol (ccp, type, tid);
>>> -
>>> -  return sym;
>>> +  while ((tid = ctf_symbol_next (ccp->fp, &i, &tname, functions)) 
>>> != CTF_ERR)
>>> +    {
>>> +      type = get_tid_type (ccp->of, tid);
>>> +      if (type == nullptr)
>>> +    continue;
>>> +      sym = new (&ccp->of->objfile_obstack) symbol;
>>> +      OBJSTAT (ccp->of, n_syms++);
>>> +      SYMBOL_TYPE (sym) = type;
>>> +      SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
>>> +      SYMBOL_ACLASS_INDEX (sym) = LOC_STATIC;
>>> +      sym->compute_and_set_names (tname, false, ccp->of->per_bfd);
>>> +      add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
>>> +      set_symbol_address (ccp->of, sym, tname);
>>> +    }
>>>   }
>>>   -/* Add an ELF STT_FUNC symbol with index IDX to the symbol 
>>> table.  */
>>> +/* Add entries in data objects section.  */
>>>   -static struct symbol *
>>> -add_stt_func (struct ctf_context *ccp, unsigned long idx)
>>> +static void
>>> +add_stt_obj (struct ctf_context *ccp)
>>>   {
>>> -  struct type *ftype, *atyp, *rettyp;
>>> -  struct symbol *sym;
>>> -  ctf_funcinfo_t finfo;
>>> -  ctf_id_t argv[32];
>>> -  uint32_t argc;
>>> -  ctf_id_t tid;
>>> -  struct type *void_type = objfile_type (ccp->of)->builtin_void;
>>> -
>>> -  if (ctf_func_info (ccp->fp, idx, &finfo) == CTF_ERR)
>>> -    return nullptr;
>>> -
>>> -  argc = finfo.ctc_argc;
>>> -  if (ctf_func_args (ccp->fp, idx, argc, argv) == CTF_ERR)
>>> -    return nullptr;
>>> -
>>> -  gdb::unique_xmalloc_ptr<char> name (ctf_type_aname_raw (ccp->fp, 
>>> idx));
>>> -  if (name == nullptr)
>>> -    return nullptr;
>>> -
>>> -  tid = ctf_lookup_by_symbol (ccp->fp, idx);
>>> -  ftype = fetch_tid_type (ccp, tid);
>>> -  if ((finfo.ctc_flags & CTF_FUNC_VARARG) != 0)
>>> -    ftype->set_has_varargs (true);
>>> -  ftype->set_num_fields (argc);
>>> -
>>> -  /* If argc is 0, it has a "void" type.  */
>>> -  if (argc != 0)
>>> -    ftype->set_fields
>>> -      ((struct field *) TYPE_ZALLOC (ftype, argc * sizeof (struct 
>>> field)));
>>> -
>>> -  /* TYPE_FIELD_TYPE must never be NULL.  Fill it with void_type, 
>>> if failed
>>> -     to find the argument type.  */
>>> -  for (int iparam = 0; iparam < argc; iparam++)
>>> -    {
>>> -      atyp = fetch_tid_type (ccp, argv[iparam]);
>>> -      if (atyp)
>>> -    ftype->field (iparam).set_type (atyp);
>>> -      else
>>> -    ftype->field (iparam).set_type (void_type);
>>> -    }
>>> +  add_stt_entries (ccp, 0);
>>> +}
>>>   -  sym = new_symbol (ccp, ftype, tid);
>>> -  rettyp = fetch_tid_type (ccp, finfo.ctc_return);
>>> -  if (rettyp != nullptr)
>>> -    SYMBOL_TYPE (sym) = rettyp;
>>> -  else
>>> -    SYMBOL_TYPE (sym) = void_type;
>>> +/* Add entries in function info section.  */
>>>   -  return sym;
>>> +static void
>>> +add_stt_func (struct ctf_context *ccp)
>>> +{
>>> +  add_stt_entries (ccp, 1);
>>>   }
>>>     /* Get text segment base for OBJFILE, TSIZE contains the segment 
>>> size.  */
>>> @@ -1317,12 +1294,71 @@ struct ctf_tid_and_type
>>>              ctf_errmsg (ctf_errno (ccp->fp)));
>>>   }
>>>   +/* Add entries in either data objects or function info section, 
>>> controlled
>>> +   by FUNCTIONS, to psymtab.  */
>>> +
>>> +static void
>>> +ctf_psymtab_add_stt_entries (ctf_dict_t *cfp, ctf_psymtab *pst,
>>> +                 struct objfile *of, int functions)
>>> +{
>>> +  ctf_next_t *i = nullptr;
>>> +  ctf_id_t tid;
>>> +  const char *tname;
>>> +
>>> +  while ((tid = ctf_symbol_next (cfp, &i, &tname, functions)) != 
>>> CTF_ERR)
>>> +    {
>>> +      uint32_t kind = ctf_type_kind (cfp, tid);
>>> +      address_class aclass;
>>> +      domain_enum tdomain;
>>> +      switch (kind)
>>> +    {
>>> +      case CTF_K_STRUCT:
>>> +      case CTF_K_UNION:
>>> +      case CTF_K_ENUM:
>>> +        tdomain = STRUCT_DOMAIN;
>>> +        break;
>>> +      default:
>>> +        tdomain = VAR_DOMAIN;
>>> +        break;
>>> +    }
>>> +
>>> +      if (kind == CTF_K_FUNCTION)
>>> +    aclass = LOC_STATIC;
>>> +      else if (kind == CTF_K_CONST)
>>> +    aclass = LOC_CONST;
>>> +      else
>>> +    aclass = LOC_TYPEDEF;
>>> +
>>> +      pst->add_psymbol (tname, true,
>>> +            tdomain, aclass, -1,
>>> +            psymbol_placement::GLOBAL,
>>> +            0, language_c, pst->context->partial_symtabs, of);
>>> +    }
>>> +}
>>> +
>>> +/* Add entries in data objects section to psymtab.  */
>>> +
>>> +static void
>>> +ctf_psymtab_add_stt_obj (ctf_dict_t *cfp, ctf_psymtab *pst,
>>> +             struct objfile *of)
>>> +{
>>> +  ctf_psymtab_add_stt_entries (cfp, pst, of, 0);
>>> +}
>>> +
>>> +/* Add entries in function info section to psymtab.  */
>>> +
>>> +static void
>>> +ctf_psymtab_add_stt_func (ctf_dict_t *cfp, ctf_psymtab *pst,
>>> +              struct objfile *of)
>>> +{
>>> +  ctf_psymtab_add_stt_entries (cfp, pst, of, 1);
>>> +}
>>> +
>>>   /* Read in full symbols for PST, and anything it depends on. */
>>>     void
>>>   ctf_psymtab::expand_psymtab (struct objfile *objfile)
>>>   {
>>> -  struct symbol *sym;
>>>     struct ctf_context *ccp;
>>>       gdb_assert (!readin);
>>> @@ -1341,21 +1377,8 @@ struct ctf_tid_and_type
>>>              ctf_errmsg (ctf_errno (ccp->fp)));
>>>       /* Add entries in data objects and function info sections.  */
>>> -  for (unsigned long i = 0; ; i++)
>>> -    {
>>> -      sym = add_stt_obj (ccp, i);
>>> -      if (sym == nullptr)
>>> -    {
>>> -      if (ctf_errno (ccp->fp) == EINVAL
>>> -          || ctf_errno (ccp->fp) == ECTF_NOSYMTAB)
>>> -        break;
>>> -      sym = add_stt_func (ccp, i);
>>> -    }
>>> -      if (sym == nullptr)
>>> -    continue;
>>> -
>>> -      set_symbol_address (ccp->of, sym, sym->linkage_name ());
>>> -    }
>>> +  add_stt_obj (ccp);
>>> +  add_stt_func (ccp);
>>>       readin = true;
>>>   }
>>> @@ -1409,6 +1432,7 @@ struct ctf_tid_and_type
>>>     static ctf_psymtab *
>>>   create_partial_symtab (const char *name,
>>> +               ctf_archive_t *arc,
>>>                  ctf_dict_t *cfp,
>>>                  psymtab_storage *partial_symtabs,
>>>                  struct objfile *objfile)
>>> @@ -1419,11 +1443,12 @@ struct ctf_tid_and_type
>>>     pst = new ctf_psymtab (name, partial_symtabs, objfile->per_bfd, 0);
>>>       ccx = XOBNEW (&objfile->objfile_obstack, struct ctf_context);
>>> +  ccx->arc = arc;
>>>     ccx->fp = cfp;
>>> +  ctf_ref (cfp);
>>>     ccx->of = objfile;
>>>     ccx->partial_symtabs = partial_symtabs;
>>>     ccx->pst = pst;
>>> -  ccx->builder = nullptr;
>>>     pst->context = ccx;
>>>       return pst;
>>> @@ -1486,7 +1511,7 @@ struct ctf_tid_and_type
>>>       ccp->pst->add_psymbol (name, false,
>>>                domain, aclass, section,
>>> -             psymbol_placement::GLOBAL,
>>> +             psymbol_placement::STATIC,
>>>                0, language_c, ccp->partial_symtabs, ccp->of);
>>>       return 0;
>>> @@ -1506,18 +1531,46 @@ struct ctf_tid_and_type
>>>     return 0;
>>>   }
>>>   +/* Start a subfile for CTF. FNAME is the name of the archive.  */
>>> +
>>> +static void
>>> +ctf_start_archive (struct ctf_context *ccx, struct objfile *of,
>>> +           const char *fname)
>>> +{
>>> +  if (ccx->builder == nullptr)
>>> +    {
>>> +      ccx->builder = new buildsym_compunit (of,
>>> +              of->original_name, nullptr, language_c, 0);
>>> +      ccx->builder->record_debugformat ("ctf");
>>> +    }
>>> +  ccx->builder->start_subfile (fname);
>>> +}
>>> +
>>>   /* Setup partial_symtab's describing each source file for which
>>>      debugging information is available.  */
>>>     static void
>>>   scan_partial_symbols (ctf_dict_t *cfp, psymtab_storage 
>>> *partial_symtabs,
>>> -              struct objfile *of)
>>> +              struct ctf_per_tu_data *tup, const char *fname)
>>>   {
>>> -  bfd *abfd = of->obfd;
>>> -  const char *name = bfd_get_filename (abfd);
>>> -  ctf_psymtab *pst = create_partial_symtab (name, cfp, 
>>> partial_symtabs, of);
>>> +  struct objfile *of = tup->of;
>>> +  bool isparent = false;
>>> +
>>> +  if (strcmp (fname, ".ctf") == 0)
>>> +    {
>>> +      fname = bfd_get_filename (of->obfd);
>>> +      isparent = true;
>>> +    }
>>> +
>>> +  ctf_psymtab *pst = create_partial_symtab (fname, tup->arc, cfp,
>>> +                        partial_symtabs, of);
>>>       struct ctf_context *ccx = pst->context;
>>> +  if (isparent == false)
>>> +    {
>>> +      ctf_start_archive (ccx, of, fname);
>>> +      ccx->pst = pst;
>>> +    }
>>>       if (ctf_type_iter (cfp, ctf_psymtab_type_cb, ccx) == CTF_ERR)
>>>       complaint (_("ctf_type_iter scan_partial_symbols failed - %s"),
>>> @@ -1530,46 +1583,33 @@ struct ctf_tid_and_type
>>>     /* Scan CTF object and function sections which correspond to each
>>>        STT_FUNC or STT_OBJECT entry in the symbol table,
>>>        pick up what init_symtab has done.  */
>>> -  for (unsigned long idx = 0; ; idx++)
>>> -    {
>>> -      ctf_id_t tid;
>>> -      if ((tid = ctf_lookup_by_symbol (cfp, idx)) == CTF_ERR)
>>> -    {
>>> -    if (ctf_errno (cfp) == EINVAL || ctf_errno (cfp) == ECTF_NOSYMTAB)
>>> -      break;    // Done, reach end of the section.
>>> -    else
>>> -      continue;
>>> -    }
>>> -      const char *tname = ctf_type_name_raw (cfp, tid);
>>> -      uint32_t kind = ctf_type_kind (cfp, tid);
>>> -      address_class aclass;
>>> -      domain_enum tdomain;
>>> -      switch (kind)
>>> -    {
>>> -      case CTF_K_STRUCT:
>>> -      case CTF_K_UNION:
>>> -      case CTF_K_ENUM:
>>> -        tdomain = STRUCT_DOMAIN;
>>> -        break;
>>> -      default:
>>> -        tdomain = VAR_DOMAIN;
>>> -        break;
>>> -    }
>>> +  ctf_psymtab_add_stt_obj (cfp, pst, of);
>>> +  ctf_psymtab_add_stt_func (cfp, pst, of);
>>>   -      if (kind == CTF_K_FUNCTION)
>>> -    aclass = LOC_STATIC;
>>> -      else if (kind == CTF_K_CONST)
>>> -    aclass = LOC_CONST;
>>> -      else
>>> -    aclass = LOC_TYPEDEF;
>>> +  pst->end ();
>>> +}
>>>   -      pst->add_psymbol (tname, false,
>>> -            tdomain, aclass, -1,
>>> -            psymbol_placement::STATIC,
>>> -            0, language_c, partial_symtabs, of);
>>> +/* Callback to build the psymtab for archive member NAME.  */
>>> +
>>> +static int
>>> +build_ctf_archive_member (ctf_dict_t *ctf, const char *name, void 
>>> *arg)
>>> +{
>>> +  struct ctf_per_tu_data *tup = (struct ctf_per_tu_data *) arg;
>>> +  ctf_dict_t *parent = tup->fp;
>>> +
>>> +  if (strcmp (name, ".ctf") != 0)
>>> +    ctf_import (ctf, parent);
>>> +
>>> +  if (info_verbose)
>>> +    {
>>> +      printf_filtered (_("Scanning archive member %s..."), name);
>>> +      gdb_flush (gdb_stdout);
>>>       }
>>>   -  pst->end ();
>>> +  psymtab_storage *pss = tup->psf->get_partial_symtabs ().get ();
>>> +  scan_partial_symbols (ctf, pss, tup, name);
>>> +
>>> +  return 0;
>>>   }
>>>     /* Read CTF debugging information from a BFD section. This is
>>> @@ -1579,6 +1619,7 @@ struct ctf_tid_and_type
>>>   void
>>>   elfctf_build_psymtabs (struct objfile *of)
>>>   {
>>> +  struct ctf_per_tu_data pcu;
>>>     bfd *abfd = of->obfd;
>>>     int err;
>>>   @@ -1593,10 +1634,18 @@ struct ctf_tid_and_type
>>>          bfd_get_filename (abfd), ctf_errmsg (err));
>>>     ctf_dict_key.emplace (of, fp);
>>>   +  pcu.fp = fp;
>>> +  pcu.of = of;
>>> +  pcu.arc = arc;
>>> +
>>>     psymbol_functions *psf = new psymbol_functions ();
>>>     psymtab_storage *partial_symtabs = psf->get_partial_symtabs 
>>> ().get ();
>>>     of->qf.emplace_front (psf);
>>> -  scan_partial_symbols (fp, partial_symtabs, of);
>>> +  pcu.psf = psf;
>>> +
>>> +  if (ctf_archive_iter (arc, build_ctf_archive_member, &pcu) < 0)
>>> +    error (_("ctf_archive_iter failed in input file %s: - %s"),
>>> +       bfd_get_filename (abfd), ctf_errmsg (err));
>>>   }
>>>     #else
>>> diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c 
>>> b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c
>>> new file mode 100644
>>> index 0000000..fe52b9e
>>> --- /dev/null
>>> +++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c
>>> @@ -0,0 +1,18 @@
>>> +struct A;
>>> +struct B
>>> +{
>>> +  int foo;
>>> +  struct A *bar;
>>> +};
>>> +
>>> +struct A
>>> +{
>>> +  long a;
>>> +  struct B *foo;
>>> +};
>>> +
>>> +static struct A *foo __attribute__((used));
>>> +
>>> +int main()
>>> +{
>>> +}
>>> diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c 
>>> b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c
>>> new file mode 100644
>>> index 0000000..aa2d177
>>> --- /dev/null
>>> +++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c
>>> @@ -0,0 +1,16 @@
>>> +struct B;
>>> +struct A
>>> +{
>>> +  long a;
>>> +  struct B *foo;
>>> +  struct C *bar;
>>> +};
>>> +
>>> +struct C
>>> +{
>>> +  struct B *foo;
>>> +  int b;
>>> +};
>>> +
>>> +static struct C *foo __attribute__((used));
>>> +static struct A *bar __attribute__((used));
>>> diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c 
>>> b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c
>>> new file mode 100644
>>> index 0000000..19947e8
>>> --- /dev/null
>>> +++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c
>>> @@ -0,0 +1,3 @@
>>> +struct A { struct B *foo; };
>>> +static struct A *a __attribute__((__used__));
>>> +static struct A *conflicty __attribute__((__used__));
>>> diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c 
>>> b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c
>>> new file mode 100644
>>> index 0000000..6e0c957
>>> --- /dev/null
>>> +++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c
>>> @@ -0,0 +1,4 @@
>>> +struct A { struct B *foo; };
>>> +struct B { struct B *next; };
>>> +static struct A *a __attribute__((__used__));
>>> +static struct B *conflicty __attribute__((__used__));
>>> diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp 
>>> b/gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp
>>> new file mode 100644
>>> index 0000000..b6e640e
>>> --- /dev/null
>>> +++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp
>>> @@ -0,0 +1,43 @@
>>> +# Copyright 2021 Free Software Foundation, Inc.
>>> +
>>> +# This program is free software; you can redistribute it and/or modify
>>> +# it under the terms of the GNU General Public License as published by
>>> +# the Free Software Foundation; either version 3 of the License, or
>>> +# (at your option) any later version.
>>> +#
>>> +# This program is distributed in the hope that it will be useful,
>>> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> +# GNU General Public License for more details.
>>> +#
>>> +# You should have received a copy of the GNU General Public License
>>> +# along with this program.  If not, see 
>>> <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!KfrttasFsnIw1ZHq2B1VVTIQZbEXNf8botBC8BmTRvyeUnbHs4wvBeakioqQKyuK$ 
>>> >.
>>> +
>>> +# This file is a subset of ptype.exp written by Rob Savoye. 
>>> (rob@cygnus.com)
>>> +
>>> +if [skip_ctf_tests] {
>>> +    unsupported "no CTF debug format support, or CTF disabled in GDB"
>>> +    return 0
>>> +}
>>> +
>>> +standard_testfile cross-tu-cyclic-1.c  cross-tu-cyclic-2.c \
>>> +    cross-tu-cyclic-3.c  cross-tu-cyclic-4.c
>>> +
>>> +# Using `-gt` generates full-fledged CTF debug information.
>>> +set opts "additional_flags=-gt -Wl,--export-dynamic"
>>> +if { [prepare_for_testing "failed to prepare" ${testfile} \
>>> +      [list $srcfile $srcfile2 $srcfile3 $srcfile4] \
>>> +      [list $opts nowarnings]] } {
>>> +    return 0
>>> +}
>>> +
>>> +# Create and source the file that provides information about the 
>>> compiler
>>> +# used to compile the test case.
>>> +if [get_compiler_info] {
>>> +    return -1
>>> +}
>>> +
>>> +# Same thing with struct and union.
>>> +gdb_test "ptype struct A" "type = struct A \{\[\r\n\]+\[ 
>>> \t\]+struct B \\*foo;\[\r\n\]+\}.*" "ptype structure A"
>>> +gdb_test "ptype struct B" "type = struct B \{\[\r\n\]+\[ 
>>> \t\]+struct B \\*next;\[\r\n\]+\}.*" "ptype structure B"
>>> +gdb_test "ptype struct C" "type = struct C \{\[\r\n\]+\[ 
>>> \t\]+struct B \\*foo;\[\r\n\]+\[ \t\]+int b;\[\r\n\]+\}.*" "ptype 
>>> structure C"
>>> diff --git a/gdb/testsuite/gdb.ctf/ctf-a.c 
>>> b/gdb/testsuite/gdb.ctf/ctf-a.c
>>> new file mode 100644
>>> index 0000000..9aa2a8f
>>> --- /dev/null
>>> +++ b/gdb/testsuite/gdb.ctf/ctf-a.c
>>> @@ -0,0 +1,32 @@
>>> +/* This test program is part of GDB, the GNU debugger.
>>> +
>>> +   Copyright 2021 Free Software Foundation, Inc.
>>> +
>>> +   This program is free software; you can redistribute it and/or 
>>> modify
>>> +   it under the terms of the GNU General Public License as 
>>> published by
>>> +   the Free Software Foundation; either version 3 of the License, or
>>> +   (at your option) any later version.
>>> +
>>> +   This program is distributed in the hope that it will be useful,
>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> +   GNU General Public License for more details.
>>> +
>>> +   You should have received a copy of the GNU General Public License
>>> +   along with this program.  If not, see 
>>> <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!KfrttasFsnIw1ZHq2B1VVTIQZbEXNf8botBC8BmTRvyeUnbHs4wvBeakioqQKyuK$ 
>>> >.  */
>>> +
>>> +#include "ctf-a.h"
>>> +
>>> +static struct A a __attribute__((used));
>>> +
>>> +extern struct C *foo ();
>>> +extern int bar ();
>>> +
>>> +int main ()
>>> +{
>>> +  struct C *cp;
>>> +  cp = foo ();
>>> +  if (cp)
>>> +    return bar ();
>>> +  return 0;
>>> +}
>>> diff --git a/gdb/testsuite/gdb.ctf/ctf-a.h 
>>> b/gdb/testsuite/gdb.ctf/ctf-a.h
>>> new file mode 100644
>>> index 0000000..297d740
>>> --- /dev/null
>>> +++ b/gdb/testsuite/gdb.ctf/ctf-a.h
>>> @@ -0,0 +1,22 @@
>>> +/* This test program is part of GDB, the GNU debugger.
>>> +
>>> +   Copyright 2021 Free Software Foundation, Inc.
>>> +
>>> +   This program is free software; you can redistribute it and/or 
>>> modify
>>> +   it under the terms of the GNU General Public License as 
>>> published by
>>> +   the Free Software Foundation; either version 3 of the License, or
>>> +   (at your option) any later version.
>>> +
>>> +   This program is distributed in the hope that it will be useful,
>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> +   GNU General Public License for more details.
>>> +
>>> +   You should have received a copy of the GNU General Public License
>>> +   along with this program.  If not, see 
>>> <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!KfrttasFsnIw1ZHq2B1VVTIQZbEXNf8botBC8BmTRvyeUnbHs4wvBeakioqQKyuK$ 
>>> >.  */
>>> +
>>> +struct A {
>>> +  struct B *b;
>>> +  struct A *next;
>>> +};
>>> +
>>> diff --git a/gdb/testsuite/gdb.ctf/ctf-b.c 
>>> b/gdb/testsuite/gdb.ctf/ctf-b.c
>>> new file mode 100644
>>> index 0000000..c3a8ce5
>>> --- /dev/null
>>> +++ b/gdb/testsuite/gdb.ctf/ctf-b.c
>>> @@ -0,0 +1,25 @@
>>> +/* This test program is part of GDB, the GNU debugger.
>>> +
>>> +   Copyright 2021 Free Software Foundation, Inc.
>>> +
>>> +   This program is free software; you can redistribute it and/or 
>>> modify
>>> +   it under the terms of the GNU General Public License as 
>>> published by
>>> +   the Free Software Foundation; either version 3 of the License, or
>>> +   (at your option) any later version.
>>> +
>>> +   This program is distributed in the hope that it will be useful,
>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> +   GNU General Public License for more details.
>>> +
>>> +   You should have received a copy of the GNU General Public License
>>> +   along with this program.  If not, see 
>>> <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!KfrttasFsnIw1ZHq2B1VVTIQZbEXNf8botBC8BmTRvyeUnbHs4wvBeakioqQKyuK$ 
>>> >.  */
>>> +
>>> +#include "ctf-b.h"
>>> +
>>> +static struct B b __attribute__((used));
>>> +
>>> +int bar ()
>>> +{
>>> +  return b.wombat;
>>> +}
>>> diff --git a/gdb/testsuite/gdb.ctf/ctf-b.h 
>>> b/gdb/testsuite/gdb.ctf/ctf-b.h
>>> new file mode 100644
>>> index 0000000..9dbdd7d
>>> --- /dev/null
>>> +++ b/gdb/testsuite/gdb.ctf/ctf-b.h
>>> @@ -0,0 +1,22 @@
>>> +/* This test program is part of GDB, the GNU debugger.
>>> +
>>> +   Copyright 2021 Free Software Foundation, Inc.
>>> +
>>> +   This program is free software; you can redistribute it and/or 
>>> modify
>>> +   it under the terms of the GNU General Public License as 
>>> published by
>>> +   the Free Software Foundation; either version 3 of the License, or
>>> +   (at your option) any later version.
>>> +
>>> +   This program is distributed in the hope that it will be useful,
>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> +   GNU General Public License for more details.
>>> +
>>> +   You should have received a copy of the GNU General Public License
>>> +   along with this program.  If not, see 
>>> <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!KfrttasFsnIw1ZHq2B1VVTIQZbEXNf8botBC8BmTRvyeUnbHs4wvBeakioqQKyuK$ 
>>> >.  */
>>> +
>>> +struct B {
>>> +  struct C *c;
>>> +  int wombat;
>>> +};
>>> +
>>> diff --git a/gdb/testsuite/gdb.ctf/ctf-c.c 
>>> b/gdb/testsuite/gdb.ctf/ctf-c.c
>>> new file mode 100644
>>> index 0000000..b4051b3
>>> --- /dev/null
>>> +++ b/gdb/testsuite/gdb.ctf/ctf-c.c
>>> @@ -0,0 +1,25 @@
>>> +/* This test program is part of GDB, the GNU debugger.
>>> +
>>> +   Copyright 2021 Free Software Foundation, Inc.
>>> +
>>> +   This program is free software; you can redistribute it and/or 
>>> modify
>>> +   it under the terms of the GNU General Public License as 
>>> published by
>>> +   the Free Software Foundation; either version 3 of the License, or
>>> +   (at your option) any later version.
>>> +
>>> +   This program is distributed in the hope that it will be useful,
>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> +   GNU General Public License for more details.
>>> +
>>> +   You should have received a copy of the GNU General Public License
>>> +   along with this program.  If not, see 
>>> <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!KfrttasFsnIw1ZHq2B1VVTIQZbEXNf8botBC8BmTRvyeUnbHs4wvBeakioqQKyuK$ 
>>> >.  */
>>> +
>>> +#include "ctf-c.h"
>>> +
>>> +static struct C c __attribute__((used));
>>> +
>>> +struct C * foo ()
>>> +{
>>> +  return &c;
>>> +}
>>> diff --git a/gdb/testsuite/gdb.ctf/ctf-c.h 
>>> b/gdb/testsuite/gdb.ctf/ctf-c.h
>>> new file mode 100644
>>> index 0000000..fb18157
>>> --- /dev/null
>>> +++ b/gdb/testsuite/gdb.ctf/ctf-c.h
>>> @@ -0,0 +1,21 @@
>>> +/* This test program is part of GDB, the GNU debugger.
>>> +
>>> +   Copyright 2021 Free Software Foundation, Inc.
>>> +
>>> +   This program is free software; you can redistribute it and/or 
>>> modify
>>> +   it under the terms of the GNU General Public License as 
>>> published by
>>> +   the Free Software Foundation; either version 3 of the License, or
>>> +   (at your option) any later version.
>>> +
>>> +   This program is distributed in the hope that it will be useful,
>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> +   GNU General Public License for more details.
>>> +
>>> +   You should have received a copy of the GNU General Public License
>>> +   along with this program.  If not, see 
>>> <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!KfrttasFsnIw1ZHq2B1VVTIQZbEXNf8botBC8BmTRvyeUnbHs4wvBeakioqQKyuK$ 
>>> >.  */
>>> +
>>> +struct C {
>>> +  struct A *a;
>>> +  int b;
>>> +};
>>> diff --git a/gdb/testsuite/gdb.ctf/multi.exp 
>>> b/gdb/testsuite/gdb.ctf/multi.exp
>>> new file mode 100644
>>> index 0000000..973115e
>>> --- /dev/null
>>> +++ b/gdb/testsuite/gdb.ctf/multi.exp
>>> @@ -0,0 +1,42 @@
>>> +# Copyright 2021 Free Software Foundation, Inc.
>>> +
>>> +# This program is free software; you can redistribute it and/or modify
>>> +# it under the terms of the GNU General Public License as published by
>>> +# the Free Software Foundation; either version 3 of the License, or
>>> +# (at your option) any later version.
>>> +#
>>> +# This program is distributed in the hope that it will be useful,
>>> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> +# GNU General Public License for more details.
>>> +#
>>> +# You should have received a copy of the GNU General Public License
>>> +# along with this program.  If not, see 
>>> <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!KfrttasFsnIw1ZHq2B1VVTIQZbEXNf8botBC8BmTRvyeUnbHs4wvBeakioqQKyuK$ 
>>> >.
>>> +
>>> +# This file is a subset of ptype.exp written by Rob Savoye. 
>>> (rob@cygnus.com)
>>> +
>>> +if [skip_ctf_tests] {
>>> +    unsupported "no CTF debug format support, or CTF disabled in GDB"
>>> +    return 0
>>> +}
>>> +
>>> +standard_testfile ctf-a.c ctf-b.c ctf-c.c
>>> +
>>> +# Using `-gt` generates full-fledged CTF debug information.
>>> +set opts "additional_flags=-gt -Wl,--export-dynamic"
>>> +if { [prepare_for_testing "failed to prepare" ${testfile} \
>>> +      [list $srcfile $srcfile2 $srcfile3] \
>>> +      [list $opts nowarnings]] } {
>>> +    return 0
>>> +}
>>> +
>>> +# Create and source the file that provides information about the 
>>> compiler
>>> +# used to compile the test case.
>>> +if [get_compiler_info] {
>>> +    return -1
>>> +}
>>> +
>>> +# Same thing with struct and union.
>>> +gdb_test "ptype struct A" "type = struct A \{\[\r\n\]+\[ 
>>> \t\]+struct B \\*b;\[\r\n\]+\[ \t\]+struct A \\*next;\[\r\n\]+\}.*" 
>>> "ptype structure A"
>>> +gdb_test "ptype struct B" "type = struct B \{\[\r\n\]+\[ 
>>> \t\]+struct C \\*c;\[\r\n\]+\[ \t\]+int \\wombat;\[\r\n\]+\}.*" 
>>> "ptype structure B"
>>> +gdb_test "ptype struct C" "type = struct C \{\[\r\n\]+\[ 
>>> \t\]+struct A \\*a;\[\r\n\]+\[ \t\]+int b;\[\r\n\]+\}.*" "ptype 
>>> structure C"

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH V5] CTF: multi-CU and archive support
  2021-05-18  0:20 [PATCH V5] CTF: multi-CU and archive support Weimin Pan
  2021-05-25  0:52 ` [PING][PATCH " Wei-min Pan
@ 2021-06-10  0:40 ` Lancelot SIX
  2021-06-10 21:15   ` Wei-min Pan
  2021-06-11 18:19   ` Tom Tromey
  2021-06-11 18:17 ` Tom Tromey
  2 siblings, 2 replies; 11+ messages in thread
From: Lancelot SIX @ 2021-06-10  0:40 UTC (permalink / raw)
  To: Weimin Pan; +Cc: gdb-patches

Hi,

I do not have much expertise on this area (and am by no mean
maintainer), but I have few questions and remarks along the patch.

I have not tested this series since I do not have a CTF capable gcc
around. I would need to search in the GCC mailing for the required
patches which I have not yet.

On Mon, May 17, 2021 at 08:20:25PM -0400, Weimin Pan via Gdb-patches wrote:
> [Changes from V4:  
>  - Treat CTF archives as CUs over dependencies to avoid over-expanding
>    psymtabs, as Tom Tromey pointed out. 
>  - Avoid calling ctf_dict_close more than once on a dictionary.]
> 
> Now gdb is capable of debugging executable, which consists of multiple
> compilation units (CUs) with the CTF debug info. An executable could
> potentially have one or more archives, which, in CTF context, contain
> conflicting types.
> 
> all changes were made in ctfread.c in which elfctf_build_psymtabs was
> modified to handle archives, via the ctf archive iterator and its callback
> build_ctf_archive_member and scan_partial_symbols was modified to scan
> archives, which are treated as subfiles, to build the psymtabs.
> 
> Also changes were made to handle CTF's data object section and function
> info section which now share the same format of their contents - an array
> of type IDs. New functions ctf_psymtab_add_stt_entries, which is called by
> ctf_psymtab_add_stt_obj and ctf_psymtab_add_stt_func, and add_stt_entries,
> which is called by add_stt_obj and add_stt_func when setting up psymtabs
> and full symtab, respectively.
> ---
>  gdb/ctfread.c                             | 311 +++++++++++++++++-------------
>  gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c |  18 ++
>  gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c |  16 ++
>  gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c |   3 +
>  gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c |   4 +
>  gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp |  43 +++++
>  gdb/testsuite/gdb.ctf/ctf-a.c             |  32 +++
>  gdb/testsuite/gdb.ctf/ctf-a.h             |  22 +++
>  gdb/testsuite/gdb.ctf/ctf-b.c             |  25 +++
>  gdb/testsuite/gdb.ctf/ctf-b.h             |  22 +++
>  gdb/testsuite/gdb.ctf/ctf-c.c             |  25 +++
>  gdb/testsuite/gdb.ctf/ctf-c.h             |  21 ++
>  gdb/testsuite/gdb.ctf/multi.exp           |  42 ++++
>  13 files changed, 453 insertions(+), 131 deletions(-)
>  create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c
>  create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c
>  create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c
>  create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c
>  create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp
>  create mode 100644 gdb/testsuite/gdb.ctf/ctf-a.c
>  create mode 100644 gdb/testsuite/gdb.ctf/ctf-a.h
>  create mode 100644 gdb/testsuite/gdb.ctf/ctf-b.c
>  create mode 100644 gdb/testsuite/gdb.ctf/ctf-b.h
>  create mode 100644 gdb/testsuite/gdb.ctf/ctf-c.c
>  create mode 100644 gdb/testsuite/gdb.ctf/ctf-c.h
>  create mode 100644 gdb/testsuite/gdb.ctf/multi.exp
> 
> diff --git a/gdb/ctfread.c b/gdb/ctfread.c
> index 23e859a..1939f40 100644
> --- a/gdb/ctfread.c
> +++ b/gdb/ctfread.c
> @@ -117,6 +117,7 @@ struct ctf_context
>    struct objfile *of;
>    psymtab_storage *partial_symtabs;
>    partial_symtab *pst;
> +  ctf_archive_t *arc;
>    struct buildsym_compunit *builder;
>  };
>  
> @@ -166,6 +167,16 @@ struct ctf_field_info
>    std::vector<struct decl_field> nested_types_list;
>  };
>  
> +/* Data held for a translation unit.  */
> +
> +struct ctf_per_tu_data
> +{
> +  ctf_dict_t *fp;
> +  struct objfile *of;
> +  ctf_archive_t *arc;
> +  psymtab_storage *pss;
> +  psymbol_functions *psf;
> +};
>  
>  /* Local function prototypes */
>  
> @@ -245,10 +256,8 @@ struct ctf_tid_and_type
>    ids.tid = tid;
>    ids.type = typ;
>    slot = (struct ctf_tid_and_type **) htab_find_slot (htab, &ids, INSERT);
> -  if (*slot)
> -    complaint (_("An internal GDB problem: ctf_ id_t %ld type already set"),
> -	       (tid));
> -  *slot = XOBNEW (&of->objfile_obstack, struct ctf_tid_and_type);
> +  if (*slot == nullptr)
> +    *slot = XOBNEW (&of->objfile_obstack, struct ctf_tid_and_type);
>    **slot = ids;
>    return typ;
>  }
> @@ -510,7 +519,7 @@ struct ctf_tid_and_type
>  	    break;
>  	}
>  
> -      add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
> +      add_symbol_to_list (sym, ccp->builder->get_file_symbols ());
>      }
>  
>    return sym;
> @@ -1143,7 +1152,8 @@ struct ctf_tid_and_type
>  	if (type)
>  	  {
>  	    sym = new_symbol (ccp, type, id);
> -	    sym->compute_and_set_names (name, false, ccp->of->per_bfd);
> +	    if (sym)

Should be

if (sym != nullptr)

> +	      sym->compute_and_set_names (name, false, ccp->of->per_bfd);
>  	  }
>  	break;
>        case CTF_K_STRUCT:
> @@ -1160,7 +1170,7 @@ struct ctf_tid_and_type
>  	SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
>  	SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT;
>  	sym->compute_and_set_names (name, false, ccp->of->per_bfd);
> -	add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
> +	add_symbol_to_list (sym, ccp->builder->get_file_symbols ());
>  	break;
>        default:
>  	complaint (_("ctf_add_var_cb: kind unsupported (%d)"), kind);
> @@ -1173,81 +1183,48 @@ struct ctf_tid_and_type
>    return 0;
>  }
>  
> -/* Add an ELF STT_OBJ symbol with index IDX to the symbol table.  */
> +/* Add entries in either data objects or function info section, controlled
> +   by FUNCTIONS.  */
>  
> -static struct symbol *
> -add_stt_obj (struct ctf_context *ccp, unsigned long idx)
> +static void
> +add_stt_entries (struct ctf_context *ccp, int functions)
>  {
> -  struct symbol *sym;
> -  struct type *type;
> +  ctf_next_t *i = nullptr;
> +  const char *tname;
>    ctf_id_t tid;
> +  struct symbol *sym = nullptr;
> +  struct type *type;
>  
> -  if ((tid = ctf_lookup_by_symbol (ccp->fp, idx)) == CTF_ERR)
> -    return nullptr;
> -
> -  type = fetch_tid_type (ccp, tid);
> -  if (type == nullptr)
> -    return nullptr;
> -
> -  sym = new_symbol (ccp, type, tid);
> -
> -  return sym;
> +  while ((tid = ctf_symbol_next (ccp->fp, &i, &tname, functions)) != CTF_ERR)
> +    {
> +      type = get_tid_type (ccp->of, tid);
> +      if (type == nullptr)
> +	continue;
> +      sym = new (&ccp->of->objfile_obstack) symbol;
> +      OBJSTAT (ccp->of, n_syms++);
> +      SYMBOL_TYPE (sym) = type;
> +      SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
> +      SYMBOL_ACLASS_INDEX (sym) = LOC_STATIC;
> +      sym->compute_and_set_names (tname, false, ccp->of->per_bfd);
> +      add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
> +      set_symbol_address (ccp->of, sym, tname);
> +    }
>  }
>  
> -/* Add an ELF STT_FUNC symbol with index IDX to the symbol table.  */
> +/* Add entries in data objects section.  */
>  
> -static struct symbol *
> -add_stt_func (struct ctf_context *ccp, unsigned long idx)
> +static void
> +add_stt_obj (struct ctf_context *ccp)
>  {
> -  struct type *ftype, *atyp, *rettyp;
> -  struct symbol *sym;
> -  ctf_funcinfo_t finfo;
> -  ctf_id_t argv[32];
> -  uint32_t argc;
> -  ctf_id_t tid;
> -  struct type *void_type = objfile_type (ccp->of)->builtin_void;
> -
> -  if (ctf_func_info (ccp->fp, idx, &finfo) == CTF_ERR)
> -    return nullptr;
> -
> -  argc = finfo.ctc_argc;
> -  if (ctf_func_args (ccp->fp, idx, argc, argv) == CTF_ERR)
> -    return nullptr;
> -
> -  gdb::unique_xmalloc_ptr<char> name (ctf_type_aname_raw (ccp->fp, idx));
> -  if (name == nullptr)
> -    return nullptr;
> -
> -  tid = ctf_lookup_by_symbol (ccp->fp, idx);
> -  ftype = fetch_tid_type (ccp, tid);
> -  if ((finfo.ctc_flags & CTF_FUNC_VARARG) != 0)
> -    ftype->set_has_varargs (true);
> -  ftype->set_num_fields (argc);
> -
> -  /* If argc is 0, it has a "void" type.  */
> -  if (argc != 0)
> -    ftype->set_fields
> -      ((struct field *) TYPE_ZALLOC (ftype, argc * sizeof (struct field)));
> -
> -  /* TYPE_FIELD_TYPE must never be NULL.  Fill it with void_type, if failed
> -     to find the argument type.  */
> -  for (int iparam = 0; iparam < argc; iparam++)
> -    {
> -      atyp = fetch_tid_type (ccp, argv[iparam]);
> -      if (atyp)
> -	ftype->field (iparam).set_type (atyp);
> -      else
> -	ftype->field (iparam).set_type (void_type);
> -    }
> +  add_stt_entries (ccp, 0);
> +}
>  
> -  sym = new_symbol (ccp, ftype, tid);
> -  rettyp = fetch_tid_type (ccp, finfo.ctc_return);
> -  if (rettyp != nullptr)
> -    SYMBOL_TYPE (sym) = rettyp;
> -  else
> -    SYMBOL_TYPE (sym) = void_type;
> +/* Add entries in function info section.  */
>  
> -  return sym;
> +static void
> +add_stt_func (struct ctf_context *ccp)
> +{
> +  add_stt_entries (ccp, 1);
>  }
>  
>  /* Get text segment base for OBJFILE, TSIZE contains the segment size.  */
> @@ -1317,12 +1294,71 @@ struct ctf_tid_and_type
>  	       ctf_errmsg (ctf_errno (ccp->fp)));
>  }
>  
> +/* Add entries in either data objects or function info section, controlled
> +   by FUNCTIONS, to psymtab.  */
> +
> +static void
> +ctf_psymtab_add_stt_entries (ctf_dict_t *cfp, ctf_psymtab *pst,
> +			     struct objfile *of, int functions)
> +{
> +  ctf_next_t *i = nullptr;
> +  ctf_id_t tid;
> +  const char *tname;
> +
> +  while ((tid = ctf_symbol_next (cfp, &i, &tname, functions)) != CTF_ERR)
> +    {
> +      uint32_t kind = ctf_type_kind (cfp, tid);
> +      address_class aclass;
> +      domain_enum tdomain;
> +      switch (kind)
> +	{
> +	  case CTF_K_STRUCT:
> +	  case CTF_K_UNION:
> +	  case CTF_K_ENUM:
> +	    tdomain = STRUCT_DOMAIN;
> +	    break;
> +	  default:
> +	    tdomain = VAR_DOMAIN;
> +	    break;
> +	}
> +
> +      if (kind == CTF_K_FUNCTION)
> +	aclass = LOC_STATIC;
> +      else if (kind == CTF_K_CONST)
> +	aclass = LOC_CONST;
> +      else
> +	aclass = LOC_TYPEDEF;
> +
> +      pst->add_psymbol (tname, true,
> +			tdomain, aclass, -1,
> +			psymbol_placement::GLOBAL,
> +			0, language_c, pst->context->partial_symtabs, of);
> +    }
> +}
> +
> +/* Add entries in data objects section to psymtab.  */
> +
> +static void
> +ctf_psymtab_add_stt_obj (ctf_dict_t *cfp, ctf_psymtab *pst,
> +			 struct objfile *of)
> +{
> +  ctf_psymtab_add_stt_entries (cfp, pst, of, 0);
> +}
> +
> +/* Add entries in function info section to psymtab.  */
> +
> +static void
> +ctf_psymtab_add_stt_func (ctf_dict_t *cfp, ctf_psymtab *pst,
> +			  struct objfile *of)
> +{
> +  ctf_psymtab_add_stt_entries (cfp, pst, of, 1);
> +}
> +
>  /* Read in full symbols for PST, and anything it depends on.  */
>  
>  void
>  ctf_psymtab::expand_psymtab (struct objfile *objfile)
>  {
> -  struct symbol *sym;
>    struct ctf_context *ccp;
>  
>    gdb_assert (!readin);
> @@ -1341,21 +1377,8 @@ struct ctf_tid_and_type
>  	       ctf_errmsg (ctf_errno (ccp->fp)));
>  
>    /* Add entries in data objects and function info sections.  */
> -  for (unsigned long i = 0; ; i++)
> -    {
> -      sym = add_stt_obj (ccp, i);
> -      if (sym == nullptr)
> -	{
> -	  if (ctf_errno (ccp->fp) == EINVAL
> -	      || ctf_errno (ccp->fp) == ECTF_NOSYMTAB)
> -	    break;
> -	  sym = add_stt_func (ccp, i);
> -	}
> -      if (sym == nullptr)
> -	continue;
> -
> -      set_symbol_address (ccp->of, sym, sym->linkage_name ());
> -    }
> +  add_stt_obj (ccp);
> +  add_stt_func (ccp);
>  
>    readin = true;
>  }
> @@ -1409,6 +1432,7 @@ struct ctf_tid_and_type
>  
>  static ctf_psymtab *
>  create_partial_symtab (const char *name,
> +		       ctf_archive_t *arc,
>  		       ctf_dict_t *cfp,
>  		       psymtab_storage *partial_symtabs,
>  		       struct objfile *objfile)
> @@ -1419,11 +1443,12 @@ struct ctf_tid_and_type
>    pst = new ctf_psymtab (name, partial_symtabs, objfile->per_bfd, 0);

I am a bit confused by this one.  As far as I can see, there is no way
it can ever be deleted.  Again, I am not so familiar with the code yet
so I might have missed something, but hopefully not.

My goto method would be to have the 'pst' field in the struct
ctf_context be a std::unique_ptr<ctf_psymtab>.  But having the
ctx_context on the objstack makes it difficult.  Even if you allocate is
with obstack_new instead of XOBNEW (because it would not be trivially
constructible anymore), the dtor would not be called when the objstack
is released.  As far as I am aware, releasing the obstack “only” releases
the underlying storage, but have no way to know that dtors should be
called.

For similar reasons (not being trivially_destructible), a ctf_psymtab
should not be allocated on the obstack.

Long story short, I do not see (yet) a clean way to have someone to
claim ownership of this newly allocated memory, and that someone being
able to free the resource at some point.  I guess similar pattern have
been faced before, and the solution should be somewhere in the codebase.

>  
>    ccx = XOBNEW (&objfile->objfile_obstack, struct ctf_context);
> +  ccx->arc = arc;
>    ccx->fp = cfp;
> +  ctf_ref (cfp);
>    ccx->of = objfile;
>    ccx->partial_symtabs = partial_symtabs;
>    ccx->pst = pst;
> -  ccx->builder = nullptr;
>    pst->context = ccx;
>  
>    return pst;
> @@ -1486,7 +1511,7 @@ struct ctf_tid_and_type
>  
>    ccp->pst->add_psymbol (name, false,
>  			 domain, aclass, section,
> -			 psymbol_placement::GLOBAL,
> +			 psymbol_placement::STATIC,
>  			 0, language_c, ccp->partial_symtabs, ccp->of);
>  
>    return 0;
> @@ -1506,18 +1531,46 @@ struct ctf_tid_and_type
>    return 0;
>  }
>  
> +/* Start a subfile for CTF. FNAME is the name of the archive.  */
> +
> +static void
> +ctf_start_archive (struct ctf_context *ccx, struct objfile *of,
> +		   const char *fname)
> +{
> +  if (ccx->builder == nullptr)
> +    {
> +      ccx->builder = new buildsym_compunit (of,
> +		      of->original_name, nullptr, language_c, 0);

This set-up code (new buildsym_compunit then
builder->record_debugformat) now exists here and in ctf_start_symtab.  I
am not quite familiar with how those can be called, but I am wondering
if there is any chance for ctf_start_symtab to be called after this code
have been executed? If so, ccx->builder will be overridden, and the
instance created here will leak.

This 'naked new' raises the same question as above. ccx (a ctf_context)
is allocated on the obstack, so no dtor is called when the memory is
released when released.  The buildsym_compunit will then end-up
dangling.  I guess this situation existed prior to this patch in
ctf_start_symtab.

> +      ccx->builder->record_debugformat ("ctf");
> +    }
> +  ccx->builder->start_subfile (fname);
> +}
> +
>  /* Setup partial_symtab's describing each source file for which
>     debugging information is available.  */
>  
>  static void
>  scan_partial_symbols (ctf_dict_t *cfp, psymtab_storage *partial_symtabs,
> -		      struct objfile *of)
> +		      struct ctf_per_tu_data *tup, const char *fname)
>  {
> -  bfd *abfd = of->obfd;
> -  const char *name = bfd_get_filename (abfd);
> -  ctf_psymtab *pst = create_partial_symtab (name, cfp, partial_symtabs, of);
> +  struct objfile *of = tup->of;
> +  bool isparent = false;
> +
> +  if (strcmp (fname, ".ctf") == 0)
> +    {
> +      fname = bfd_get_filename (of->obfd);
> +      isparent = true;
> +    }
> +
> +  ctf_psymtab *pst = create_partial_symtab (fname, tup->arc, cfp,
> +					    partial_symtabs, of);
>  
>    struct ctf_context *ccx = pst->context;
> +  if (isparent == false)
> +    {
> +      ctf_start_archive (ccx, of, fname);
> +      ccx->pst = pst;
> +    }
>  
>    if (ctf_type_iter (cfp, ctf_psymtab_type_cb, ccx) == CTF_ERR)
>      complaint (_("ctf_type_iter scan_partial_symbols failed - %s"),
> @@ -1530,46 +1583,33 @@ struct ctf_tid_and_type
>    /* Scan CTF object and function sections which correspond to each
>       STT_FUNC or STT_OBJECT entry in the symbol table,
>       pick up what init_symtab has done.  */
> -  for (unsigned long idx = 0; ; idx++)
> -    {
> -      ctf_id_t tid;
> -      if ((tid = ctf_lookup_by_symbol (cfp, idx)) == CTF_ERR)
> -	{
> -	if (ctf_errno (cfp) == EINVAL || ctf_errno (cfp) == ECTF_NOSYMTAB)
> -	  break;	// Done, reach end of the section.
> -	else
> -	  continue;
> -	}
> -      const char *tname = ctf_type_name_raw (cfp, tid);
> -      uint32_t kind = ctf_type_kind (cfp, tid);
> -      address_class aclass;
> -      domain_enum tdomain;
> -      switch (kind)
> -	{
> -	  case CTF_K_STRUCT:
> -	  case CTF_K_UNION:
> -	  case CTF_K_ENUM:
> -	    tdomain = STRUCT_DOMAIN;
> -	    break;
> -	  default:
> -	    tdomain = VAR_DOMAIN;
> -	    break;
> -	}
> +  ctf_psymtab_add_stt_obj (cfp, pst, of);
> +  ctf_psymtab_add_stt_func (cfp, pst, of);
>  
> -      if (kind == CTF_K_FUNCTION)
> -	aclass = LOC_STATIC;
> -      else if (kind == CTF_K_CONST)
> -	aclass = LOC_CONST;
> -      else
> -	aclass = LOC_TYPEDEF;
> +  pst->end ();
> +}
>  
> -      pst->add_psymbol (tname, false,
> -			tdomain, aclass, -1,
> -			psymbol_placement::STATIC,
> -			0, language_c, partial_symtabs, of);
> +/* Callback to build the psymtab for archive member NAME.  */
> +
> +static int
> +build_ctf_archive_member (ctf_dict_t *ctf, const char *name, void *arg)
> +{
> +  struct ctf_per_tu_data *tup = (struct ctf_per_tu_data *) arg;
> +  ctf_dict_t *parent = tup->fp;
> +
> +  if (strcmp (name, ".ctf") != 0)
> +    ctf_import (ctf, parent);
> +
> +  if (info_verbose)
> +    {
> +      printf_filtered (_("Scanning archive member %s..."), name);
> +      gdb_flush (gdb_stdout);
>      }
>  
> -  pst->end ();
> +  psymtab_storage *pss = tup->psf->get_partial_symtabs ().get ();
> +  scan_partial_symbols (ctf, pss, tup, name);
> +
> +  return 0;
>  }
>  
>  /* Read CTF debugging information from a BFD section.  This is
> @@ -1579,6 +1619,7 @@ struct ctf_tid_and_type
>  void
>  elfctf_build_psymtabs (struct objfile *of)
>  {
> +  struct ctf_per_tu_data pcu;
>    bfd *abfd = of->obfd;
>    int err;
>  
> @@ -1593,10 +1634,18 @@ struct ctf_tid_and_type
>  	   bfd_get_filename (abfd), ctf_errmsg (err));
>    ctf_dict_key.emplace (of, fp);
>  
> +  pcu.fp = fp;
> +  pcu.of = of;
> +  pcu.arc = arc;
> +
>    psymbol_functions *psf = new psymbol_functions ();
>    psymtab_storage *partial_symtabs = psf->get_partial_symtabs ().get ();
>    of->qf.emplace_front (psf);
> -  scan_partial_symbols (fp, partial_symtabs, of);

By removing this call, 'partial_symtabs' (declared 2 lines above) is
now unused and should also be removed.

I hope those remarks / questions are useful.

Lancelot

> +  pcu.psf = psf;
> +
> +  if (ctf_archive_iter (arc, build_ctf_archive_member, &pcu) < 0)
> +    error (_("ctf_archive_iter failed in input file %s: - %s"),
> +	   bfd_get_filename (abfd), ctf_errmsg (err));
>  }
>  
>  #else
> diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c
> new file mode 100644
> index 0000000..fe52b9e
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c
> @@ -0,0 +1,18 @@
> +struct A;
> +struct B
> +{
> +  int foo;
> +  struct A *bar;
> +};
> +
> +struct A
> +{
> +  long a;
> +  struct B *foo;
> +};
> +
> +static struct A *foo __attribute__((used));
> +
> +int main()
> +{
> +}
> diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c
> new file mode 100644
> index 0000000..aa2d177
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c
> @@ -0,0 +1,16 @@
> +struct B;
> +struct A
> +{
> +  long a;
> +  struct B *foo;
> +  struct C *bar;
> +};
> +
> +struct C
> +{
> +  struct B *foo;
> +  int b;
> +};
> +
> +static struct C *foo __attribute__((used));
> +static struct A *bar __attribute__((used));
> diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c
> new file mode 100644
> index 0000000..19947e8
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c
> @@ -0,0 +1,3 @@
> +struct A { struct B *foo; };
> +static struct A *a __attribute__((__used__));
> +static struct A *conflicty __attribute__((__used__));
> diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c
> new file mode 100644
> index 0000000..6e0c957
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c
> @@ -0,0 +1,4 @@
> +struct A { struct B *foo; };
> +struct B { struct B *next; };
> +static struct A *a __attribute__((__used__));
> +static struct B *conflicty __attribute__((__used__));
> diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp b/gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp
> new file mode 100644
> index 0000000..b6e640e
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp
> @@ -0,0 +1,43 @@
> +# Copyright 2021 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +
> +# This file is a subset of ptype.exp written by Rob Savoye. (rob@cygnus.com)
> +
> +if [skip_ctf_tests] {
> +    unsupported "no CTF debug format support, or CTF disabled in GDB"
> +    return 0
> +}
> +
> +standard_testfile cross-tu-cyclic-1.c  cross-tu-cyclic-2.c \
> +	cross-tu-cyclic-3.c  cross-tu-cyclic-4.c
> +
> +# Using `-gt` generates full-fledged CTF debug information.
> +set opts "additional_flags=-gt -Wl,--export-dynamic"
> +if { [prepare_for_testing "failed to prepare" ${testfile} \
> +	  [list $srcfile $srcfile2 $srcfile3 $srcfile4] \
> +	  [list $opts nowarnings]] } {
> +    return 0
> +}
> +
> +# Create and source the file that provides information about the compiler
> +# used to compile the test case.
> +if [get_compiler_info] {
> +    return -1
> +}
> +
> +# Same thing with struct and union.
> +gdb_test "ptype struct A" "type = struct A \{\[\r\n\]+\[ \t\]+struct B \\*foo;\[\r\n\]+\}.*" "ptype structure A"
> +gdb_test "ptype struct B" "type = struct B \{\[\r\n\]+\[ \t\]+struct B \\*next;\[\r\n\]+\}.*" "ptype structure B"
> +gdb_test "ptype struct C" "type = struct C \{\[\r\n\]+\[ \t\]+struct B \\*foo;\[\r\n\]+\[ \t\]+int b;\[\r\n\]+\}.*" "ptype structure C"
> diff --git a/gdb/testsuite/gdb.ctf/ctf-a.c b/gdb/testsuite/gdb.ctf/ctf-a.c
> new file mode 100644
> index 0000000..9aa2a8f
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ctf/ctf-a.c
> @@ -0,0 +1,32 @@
> +/* This test program is part of GDB, the GNU debugger.
> +
> +   Copyright 2021 Free Software Foundation, Inc.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +#include "ctf-a.h"
> +
> +static struct A a __attribute__((used));
> +
> +extern struct C *foo ();
> +extern int bar ();
> +
> +int main ()
> +{
> +  struct C *cp;
> +  cp = foo ();
> +  if (cp)
> +    return bar ();
> +  return 0;
> +}
> diff --git a/gdb/testsuite/gdb.ctf/ctf-a.h b/gdb/testsuite/gdb.ctf/ctf-a.h
> new file mode 100644
> index 0000000..297d740
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ctf/ctf-a.h
> @@ -0,0 +1,22 @@
> +/* This test program is part of GDB, the GNU debugger.
> +
> +   Copyright 2021 Free Software Foundation, Inc.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +struct A {
> +  struct B *b;
> +  struct A *next;
> +};
> +
> diff --git a/gdb/testsuite/gdb.ctf/ctf-b.c b/gdb/testsuite/gdb.ctf/ctf-b.c
> new file mode 100644
> index 0000000..c3a8ce5
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ctf/ctf-b.c
> @@ -0,0 +1,25 @@
> +/* This test program is part of GDB, the GNU debugger.
> +
> +   Copyright 2021 Free Software Foundation, Inc.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +#include "ctf-b.h"
> +
> +static struct B b __attribute__((used));
> +
> +int bar ()
> +{
> +  return b.wombat;
> +}
> diff --git a/gdb/testsuite/gdb.ctf/ctf-b.h b/gdb/testsuite/gdb.ctf/ctf-b.h
> new file mode 100644
> index 0000000..9dbdd7d
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ctf/ctf-b.h
> @@ -0,0 +1,22 @@
> +/* This test program is part of GDB, the GNU debugger.
> +
> +   Copyright 2021 Free Software Foundation, Inc.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +struct B {
> +  struct C *c;
> +  int wombat;
> +};
> +
> diff --git a/gdb/testsuite/gdb.ctf/ctf-c.c b/gdb/testsuite/gdb.ctf/ctf-c.c
> new file mode 100644
> index 0000000..b4051b3
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ctf/ctf-c.c
> @@ -0,0 +1,25 @@
> +/* This test program is part of GDB, the GNU debugger.
> +
> +   Copyright 2021 Free Software Foundation, Inc.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +#include "ctf-c.h"
> +
> +static struct C c __attribute__((used));
> +
> +struct C * foo ()
> +{
> +  return &c;
> +}
> diff --git a/gdb/testsuite/gdb.ctf/ctf-c.h b/gdb/testsuite/gdb.ctf/ctf-c.h
> new file mode 100644
> index 0000000..fb18157
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ctf/ctf-c.h
> @@ -0,0 +1,21 @@
> +/* This test program is part of GDB, the GNU debugger.
> +
> +   Copyright 2021 Free Software Foundation, Inc.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +struct C {
> +  struct A *a;
> +  int b;
> +};
> diff --git a/gdb/testsuite/gdb.ctf/multi.exp b/gdb/testsuite/gdb.ctf/multi.exp
> new file mode 100644
> index 0000000..973115e
> --- /dev/null
> +++ b/gdb/testsuite/gdb.ctf/multi.exp
> @@ -0,0 +1,42 @@
> +# Copyright 2021 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +
> +# This file is a subset of ptype.exp written by Rob Savoye. (rob@cygnus.com)
> +
> +if [skip_ctf_tests] {
> +    unsupported "no CTF debug format support, or CTF disabled in GDB"
> +    return 0
> +}
> +
> +standard_testfile ctf-a.c ctf-b.c ctf-c.c
> +
> +# Using `-gt` generates full-fledged CTF debug information.
> +set opts "additional_flags=-gt -Wl,--export-dynamic"
> +if { [prepare_for_testing "failed to prepare" ${testfile} \
> +	  [list $srcfile $srcfile2 $srcfile3] \
> +	  [list $opts nowarnings]] } {
> +    return 0
> +}
> +
> +# Create and source the file that provides information about the compiler
> +# used to compile the test case.
> +if [get_compiler_info] {
> +    return -1
> +}
> +
> +# Same thing with struct and union.
> +gdb_test "ptype struct A" "type = struct A \{\[\r\n\]+\[ \t\]+struct B \\*b;\[\r\n\]+\[ \t\]+struct A \\*next;\[\r\n\]+\}.*" "ptype structure A"
> +gdb_test "ptype struct B" "type = struct B \{\[\r\n\]+\[ \t\]+struct C \\*c;\[\r\n\]+\[ \t\]+int \\wombat;\[\r\n\]+\}.*" "ptype structure B"
> +gdb_test "ptype struct C" "type = struct C \{\[\r\n\]+\[ \t\]+struct A \\*a;\[\r\n\]+\[ \t\]+int b;\[\r\n\]+\}.*" "ptype structure C"
> -- 
> 1.8.3.1
> 

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH V5] CTF: multi-CU and archive support
  2021-06-10  0:40 ` [PATCH " Lancelot SIX
@ 2021-06-10 21:15   ` Wei-min Pan
  2021-06-11 23:07     ` Lancelot SIX
  2021-06-11 18:19   ` Tom Tromey
  1 sibling, 1 reply; 11+ messages in thread
From: Wei-min Pan @ 2021-06-10 21:15 UTC (permalink / raw)
  To: Lancelot SIX; +Cc: gdb-patches


On 6/9/2021 5:40 PM, Lancelot SIX wrote:
> Hi,
>
> I do not have much expertise on this area (and am by no mean
> maintainer), but I have few questions and remarks along the patch.
>
> I have not tested this series since I do not have a CTF capable gcc
> around. I would need to search in the GCC mailing for the required
> patches which I have not yet.
Hi,

You can find the latest gcc patch series for CTF support, which is 
currently under review, here:

http://gcc.1065356.n8.nabble.com/PATCH-V9-0-7-Support-for-the-CTF-and-BTF-debug-formats-td1897109.html

Also please make sure to use a binutils version with CTF support.

>
> On Mon, May 17, 2021 at 08:20:25PM -0400, Weimin Pan via Gdb-patches wrote:
>> [Changes from V4:
>>   - Treat CTF archives as CUs over dependencies to avoid over-expanding
>>     psymtabs, as Tom Tromey pointed out.
>>   - Avoid calling ctf_dict_close more than once on a dictionary.]
>>
>> Now gdb is capable of debugging executable, which consists of multiple
>> compilation units (CUs) with the CTF debug info. An executable could
>> potentially have one or more archives, which, in CTF context, contain
>> conflicting types.
>>
>> all changes were made in ctfread.c in which elfctf_build_psymtabs was
>> modified to handle archives, via the ctf archive iterator and its callback
>> build_ctf_archive_member and scan_partial_symbols was modified to scan
>> archives, which are treated as subfiles, to build the psymtabs.
>>
>> Also changes were made to handle CTF's data object section and function
>> info section which now share the same format of their contents - an array
>> of type IDs. New functions ctf_psymtab_add_stt_entries, which is called by
>> ctf_psymtab_add_stt_obj and ctf_psymtab_add_stt_func, and add_stt_entries,
>> which is called by add_stt_obj and add_stt_func when setting up psymtabs
>> and full symtab, respectively.
>> ---
>>   gdb/ctfread.c                             | 311 +++++++++++++++++-------------
>>   gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c |  18 ++
>>   gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c |  16 ++
>>   gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c |   3 +
>>   gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c |   4 +
>>   gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp |  43 +++++
>>   gdb/testsuite/gdb.ctf/ctf-a.c             |  32 +++
>>   gdb/testsuite/gdb.ctf/ctf-a.h             |  22 +++
>>   gdb/testsuite/gdb.ctf/ctf-b.c             |  25 +++
>>   gdb/testsuite/gdb.ctf/ctf-b.h             |  22 +++
>>   gdb/testsuite/gdb.ctf/ctf-c.c             |  25 +++
>>   gdb/testsuite/gdb.ctf/ctf-c.h             |  21 ++
>>   gdb/testsuite/gdb.ctf/multi.exp           |  42 ++++
>>   13 files changed, 453 insertions(+), 131 deletions(-)
>>   create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c
>>   create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c
>>   create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c
>>   create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c
>>   create mode 100644 gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp
>>   create mode 100644 gdb/testsuite/gdb.ctf/ctf-a.c
>>   create mode 100644 gdb/testsuite/gdb.ctf/ctf-a.h
>>   create mode 100644 gdb/testsuite/gdb.ctf/ctf-b.c
>>   create mode 100644 gdb/testsuite/gdb.ctf/ctf-b.h
>>   create mode 100644 gdb/testsuite/gdb.ctf/ctf-c.c
>>   create mode 100644 gdb/testsuite/gdb.ctf/ctf-c.h
>>   create mode 100644 gdb/testsuite/gdb.ctf/multi.exp
>>
>> diff --git a/gdb/ctfread.c b/gdb/ctfread.c
>> index 23e859a..1939f40 100644
>> --- a/gdb/ctfread.c
>> +++ b/gdb/ctfread.c
>> @@ -117,6 +117,7 @@ struct ctf_context
>>     struct objfile *of;
>>     psymtab_storage *partial_symtabs;
>>     partial_symtab *pst;
>> +  ctf_archive_t *arc;
>>     struct buildsym_compunit *builder;
>>   };
>>   
>> @@ -166,6 +167,16 @@ struct ctf_field_info
>>     std::vector<struct decl_field> nested_types_list;
>>   };
>>   
>> +/* Data held for a translation unit.  */
>> +
>> +struct ctf_per_tu_data
>> +{
>> +  ctf_dict_t *fp;
>> +  struct objfile *of;
>> +  ctf_archive_t *arc;
>> +  psymtab_storage *pss;
>> +  psymbol_functions *psf;
>> +};
>>   
>>   /* Local function prototypes */
>>   
>> @@ -245,10 +256,8 @@ struct ctf_tid_and_type
>>     ids.tid = tid;
>>     ids.type = typ;
>>     slot = (struct ctf_tid_and_type **) htab_find_slot (htab, &ids, INSERT);
>> -  if (*slot)
>> -    complaint (_("An internal GDB problem: ctf_ id_t %ld type already set"),
>> -	       (tid));
>> -  *slot = XOBNEW (&of->objfile_obstack, struct ctf_tid_and_type);
>> +  if (*slot == nullptr)
>> +    *slot = XOBNEW (&of->objfile_obstack, struct ctf_tid_and_type);
>>     **slot = ids;
>>     return typ;
>>   }
>> @@ -510,7 +519,7 @@ struct ctf_tid_and_type
>>   	    break;
>>   	}
>>   
>> -      add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
>> +      add_symbol_to_list (sym, ccp->builder->get_file_symbols ());
>>       }
>>   
>>     return sym;
>> @@ -1143,7 +1152,8 @@ struct ctf_tid_and_type
>>   	if (type)
>>   	  {
>>   	    sym = new_symbol (ccp, type, id);
>> -	    sym->compute_and_set_names (name, false, ccp->of->per_bfd);
>> +	    if (sym)
> Should be
>
> if (sym != nullptr)

OK.

>> +	      sym->compute_and_set_names (name, false, ccp->of->per_bfd);
>>   	  }
>>   	break;
>>         case CTF_K_STRUCT:
>> @@ -1160,7 +1170,7 @@ struct ctf_tid_and_type
>>   	SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
>>   	SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT;
>>   	sym->compute_and_set_names (name, false, ccp->of->per_bfd);
>> -	add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
>> +	add_symbol_to_list (sym, ccp->builder->get_file_symbols ());
>>   	break;
>>         default:
>>   	complaint (_("ctf_add_var_cb: kind unsupported (%d)"), kind);
>> @@ -1173,81 +1183,48 @@ struct ctf_tid_and_type
>>     return 0;
>>   }
>>   
>> -/* Add an ELF STT_OBJ symbol with index IDX to the symbol table.  */
>> +/* Add entries in either data objects or function info section, controlled
>> +   by FUNCTIONS.  */
>>   
>> -static struct symbol *
>> -add_stt_obj (struct ctf_context *ccp, unsigned long idx)
>> +static void
>> +add_stt_entries (struct ctf_context *ccp, int functions)
>>   {
>> -  struct symbol *sym;
>> -  struct type *type;
>> +  ctf_next_t *i = nullptr;
>> +  const char *tname;
>>     ctf_id_t tid;
>> +  struct symbol *sym = nullptr;
>> +  struct type *type;
>>   
>> -  if ((tid = ctf_lookup_by_symbol (ccp->fp, idx)) == CTF_ERR)
>> -    return nullptr;
>> -
>> -  type = fetch_tid_type (ccp, tid);
>> -  if (type == nullptr)
>> -    return nullptr;
>> -
>> -  sym = new_symbol (ccp, type, tid);
>> -
>> -  return sym;
>> +  while ((tid = ctf_symbol_next (ccp->fp, &i, &tname, functions)) != CTF_ERR)
>> +    {
>> +      type = get_tid_type (ccp->of, tid);
>> +      if (type == nullptr)
>> +	continue;
>> +      sym = new (&ccp->of->objfile_obstack) symbol;
>> +      OBJSTAT (ccp->of, n_syms++);
>> +      SYMBOL_TYPE (sym) = type;
>> +      SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
>> +      SYMBOL_ACLASS_INDEX (sym) = LOC_STATIC;
>> +      sym->compute_and_set_names (tname, false, ccp->of->per_bfd);
>> +      add_symbol_to_list (sym, ccp->builder->get_global_symbols ());
>> +      set_symbol_address (ccp->of, sym, tname);
>> +    }
>>   }
>>   
>> -/* Add an ELF STT_FUNC symbol with index IDX to the symbol table.  */
>> +/* Add entries in data objects section.  */
>>   
>> -static struct symbol *
>> -add_stt_func (struct ctf_context *ccp, unsigned long idx)
>> +static void
>> +add_stt_obj (struct ctf_context *ccp)
>>   {
>> -  struct type *ftype, *atyp, *rettyp;
>> -  struct symbol *sym;
>> -  ctf_funcinfo_t finfo;
>> -  ctf_id_t argv[32];
>> -  uint32_t argc;
>> -  ctf_id_t tid;
>> -  struct type *void_type = objfile_type (ccp->of)->builtin_void;
>> -
>> -  if (ctf_func_info (ccp->fp, idx, &finfo) == CTF_ERR)
>> -    return nullptr;
>> -
>> -  argc = finfo.ctc_argc;
>> -  if (ctf_func_args (ccp->fp, idx, argc, argv) == CTF_ERR)
>> -    return nullptr;
>> -
>> -  gdb::unique_xmalloc_ptr<char> name (ctf_type_aname_raw (ccp->fp, idx));
>> -  if (name == nullptr)
>> -    return nullptr;
>> -
>> -  tid = ctf_lookup_by_symbol (ccp->fp, idx);
>> -  ftype = fetch_tid_type (ccp, tid);
>> -  if ((finfo.ctc_flags & CTF_FUNC_VARARG) != 0)
>> -    ftype->set_has_varargs (true);
>> -  ftype->set_num_fields (argc);
>> -
>> -  /* If argc is 0, it has a "void" type.  */
>> -  if (argc != 0)
>> -    ftype->set_fields
>> -      ((struct field *) TYPE_ZALLOC (ftype, argc * sizeof (struct field)));
>> -
>> -  /* TYPE_FIELD_TYPE must never be NULL.  Fill it with void_type, if failed
>> -     to find the argument type.  */
>> -  for (int iparam = 0; iparam < argc; iparam++)
>> -    {
>> -      atyp = fetch_tid_type (ccp, argv[iparam]);
>> -      if (atyp)
>> -	ftype->field (iparam).set_type (atyp);
>> -      else
>> -	ftype->field (iparam).set_type (void_type);
>> -    }
>> +  add_stt_entries (ccp, 0);
>> +}
>>   
>> -  sym = new_symbol (ccp, ftype, tid);
>> -  rettyp = fetch_tid_type (ccp, finfo.ctc_return);
>> -  if (rettyp != nullptr)
>> -    SYMBOL_TYPE (sym) = rettyp;
>> -  else
>> -    SYMBOL_TYPE (sym) = void_type;
>> +/* Add entries in function info section.  */
>>   
>> -  return sym;
>> +static void
>> +add_stt_func (struct ctf_context *ccp)
>> +{
>> +  add_stt_entries (ccp, 1);
>>   }
>>   
>>   /* Get text segment base for OBJFILE, TSIZE contains the segment size.  */
>> @@ -1317,12 +1294,71 @@ struct ctf_tid_and_type
>>   	       ctf_errmsg (ctf_errno (ccp->fp)));
>>   }
>>   
>> +/* Add entries in either data objects or function info section, controlled
>> +   by FUNCTIONS, to psymtab.  */
>> +
>> +static void
>> +ctf_psymtab_add_stt_entries (ctf_dict_t *cfp, ctf_psymtab *pst,
>> +			     struct objfile *of, int functions)
>> +{
>> +  ctf_next_t *i = nullptr;
>> +  ctf_id_t tid;
>> +  const char *tname;
>> +
>> +  while ((tid = ctf_symbol_next (cfp, &i, &tname, functions)) != CTF_ERR)
>> +    {
>> +      uint32_t kind = ctf_type_kind (cfp, tid);
>> +      address_class aclass;
>> +      domain_enum tdomain;
>> +      switch (kind)
>> +	{
>> +	  case CTF_K_STRUCT:
>> +	  case CTF_K_UNION:
>> +	  case CTF_K_ENUM:
>> +	    tdomain = STRUCT_DOMAIN;
>> +	    break;
>> +	  default:
>> +	    tdomain = VAR_DOMAIN;
>> +	    break;
>> +	}
>> +
>> +      if (kind == CTF_K_FUNCTION)
>> +	aclass = LOC_STATIC;
>> +      else if (kind == CTF_K_CONST)
>> +	aclass = LOC_CONST;
>> +      else
>> +	aclass = LOC_TYPEDEF;
>> +
>> +      pst->add_psymbol (tname, true,
>> +			tdomain, aclass, -1,
>> +			psymbol_placement::GLOBAL,
>> +			0, language_c, pst->context->partial_symtabs, of);
>> +    }
>> +}
>> +
>> +/* Add entries in data objects section to psymtab.  */
>> +
>> +static void
>> +ctf_psymtab_add_stt_obj (ctf_dict_t *cfp, ctf_psymtab *pst,
>> +			 struct objfile *of)
>> +{
>> +  ctf_psymtab_add_stt_entries (cfp, pst, of, 0);
>> +}
>> +
>> +/* Add entries in function info section to psymtab.  */
>> +
>> +static void
>> +ctf_psymtab_add_stt_func (ctf_dict_t *cfp, ctf_psymtab *pst,
>> +			  struct objfile *of)
>> +{
>> +  ctf_psymtab_add_stt_entries (cfp, pst, of, 1);
>> +}
>> +
>>   /* Read in full symbols for PST, and anything it depends on.  */
>>   
>>   void
>>   ctf_psymtab::expand_psymtab (struct objfile *objfile)
>>   {
>> -  struct symbol *sym;
>>     struct ctf_context *ccp;
>>   
>>     gdb_assert (!readin);
>> @@ -1341,21 +1377,8 @@ struct ctf_tid_and_type
>>   	       ctf_errmsg (ctf_errno (ccp->fp)));
>>   
>>     /* Add entries in data objects and function info sections.  */
>> -  for (unsigned long i = 0; ; i++)
>> -    {
>> -      sym = add_stt_obj (ccp, i);
>> -      if (sym == nullptr)
>> -	{
>> -	  if (ctf_errno (ccp->fp) == EINVAL
>> -	      || ctf_errno (ccp->fp) == ECTF_NOSYMTAB)
>> -	    break;
>> -	  sym = add_stt_func (ccp, i);
>> -	}
>> -      if (sym == nullptr)
>> -	continue;
>> -
>> -      set_symbol_address (ccp->of, sym, sym->linkage_name ());
>> -    }
>> +  add_stt_obj (ccp);
>> +  add_stt_func (ccp);
>>   
>>     readin = true;
>>   }
>> @@ -1409,6 +1432,7 @@ struct ctf_tid_and_type
>>   
>>   static ctf_psymtab *
>>   create_partial_symtab (const char *name,
>> +		       ctf_archive_t *arc,
>>   		       ctf_dict_t *cfp,
>>   		       psymtab_storage *partial_symtabs,
>>   		       struct objfile *objfile)
>> @@ -1419,11 +1443,12 @@ struct ctf_tid_and_type
>>     pst = new ctf_psymtab (name, partial_symtabs, objfile->per_bfd, 0);
> I am a bit confused by this one.  As far as I can see, there is no way
> it can ever be deleted.  Again, I am not so familiar with the code yet
> so I might have missed something, but hopefully not.

I believe  the psymtab_discarder's dtor should take care of discarding 
all built partial
symbol tables. So I'm not sure if this is a CTF specific issue.

> My goto method would be to have the 'pst' field in the struct
> ctf_context be a std::unique_ptr<ctf_psymtab>.  But having the
> ctx_context on the objstack makes it difficult.  Even if you allocate is
> with obstack_new instead of XOBNEW (because it would not be trivially
> constructible anymore), the dtor would not be called when the objstack
> is released.  As far as I am aware, releasing the obstack “only” releases
> the underlying storage, but have no way to know that dtors should be
> called.

One way to avoid dealing with either the storage or dtor issue is to 
declare:

         struct ctf_context context;

in struct ctf_psymtab.

>
> For similar reasons (not being trivially_destructible), a ctf_psymtab
> should not be allocated on the obstack.
>
> Long story short, I do not see (yet) a clean way to have someone to
> claim ownership of this newly allocated memory, and that someone being
> able to free the resource at some point.  I guess similar pattern have
> been faced before, and the solution should be somewhere in the codebase.
>
>>   
>>     ccx = XOBNEW (&objfile->objfile_obstack, struct ctf_context);
>> +  ccx->arc = arc;
>>     ccx->fp = cfp;
>> +  ctf_ref (cfp);
>>     ccx->of = objfile;
>>     ccx->partial_symtabs = partial_symtabs;
>>     ccx->pst = pst;
>> -  ccx->builder = nullptr;
>>     pst->context = ccx;
>>   
>>     return pst;
>> @@ -1486,7 +1511,7 @@ struct ctf_tid_and_type
>>   
>>     ccp->pst->add_psymbol (name, false,
>>   			 domain, aclass, section,
>> -			 psymbol_placement::GLOBAL,
>> +			 psymbol_placement::STATIC,
>>   			 0, language_c, ccp->partial_symtabs, ccp->of);
>>   
>>     return 0;
>> @@ -1506,18 +1531,46 @@ struct ctf_tid_and_type
>>     return 0;
>>   }
>>   
>> +/* Start a subfile for CTF. FNAME is the name of the archive.  */
>> +
>> +static void
>> +ctf_start_archive (struct ctf_context *ccx, struct objfile *of,
>> +		   const char *fname)
>> +{
>> +  if (ccx->builder == nullptr)
>> +    {
>> +      ccx->builder = new buildsym_compunit (of,
>> +		      of->original_name, nullptr, language_c, 0);
> This set-up code (new buildsym_compunit then
> builder->record_debugformat) now exists here and in ctf_start_symtab.  I
> am not quite familiar with how those can be called, but I am wondering
> if there is any chance for ctf_start_symtab to be called after this code
> have been executed? If so, ccx->builder will be overridden, and the
> instance created here will leak.

ctf_start_symtab gets called to handle the main CU while ctf_start_archive
gets called to handle each archive which, in the CTF context, is just a CU
and contains the CTF debugging info for conflicting types. Since the mian CU
always gets processed before its archives do. it's not possible that the 
builder
field will get overridden.

> This 'naked new' raises the same question as above. ccx (a ctf_context)
> is allocated on the obstack, so no dtor is called when the memory is
> released when released.  The buildsym_compunit will then end-up
> dangling.  I guess this situation existed prior to this patch in
> ctf_start_symtab.
>
>> +      ccx->builder->record_debugformat ("ctf");
>> +    }
>> +  ccx->builder->start_subfile (fname);
>> +}
>> +
>>   /* Setup partial_symtab's describing each source file for which
>>      debugging information is available.  */
>>   
>>   static void
>>   scan_partial_symbols (ctf_dict_t *cfp, psymtab_storage *partial_symtabs,
>> -		      struct objfile *of)
>> +		      struct ctf_per_tu_data *tup, const char *fname)
>>   {
>> -  bfd *abfd = of->obfd;
>> -  const char *name = bfd_get_filename (abfd);
>> -  ctf_psymtab *pst = create_partial_symtab (name, cfp, partial_symtabs, of);
>> +  struct objfile *of = tup->of;
>> +  bool isparent = false;
>> +
>> +  if (strcmp (fname, ".ctf") == 0)
>> +    {
>> +      fname = bfd_get_filename (of->obfd);
>> +      isparent = true;
>> +    }
>> +
>> +  ctf_psymtab *pst = create_partial_symtab (fname, tup->arc, cfp,
>> +					    partial_symtabs, of);
>>   
>>     struct ctf_context *ccx = pst->context;
>> +  if (isparent == false)
>> +    {
>> +      ctf_start_archive (ccx, of, fname);
>> +      ccx->pst = pst;
>> +    }
>>   
>>     if (ctf_type_iter (cfp, ctf_psymtab_type_cb, ccx) == CTF_ERR)
>>       complaint (_("ctf_type_iter scan_partial_symbols failed - %s"),
>> @@ -1530,46 +1583,33 @@ struct ctf_tid_and_type
>>     /* Scan CTF object and function sections which correspond to each
>>        STT_FUNC or STT_OBJECT entry in the symbol table,
>>        pick up what init_symtab has done.  */
>> -  for (unsigned long idx = 0; ; idx++)
>> -    {
>> -      ctf_id_t tid;
>> -      if ((tid = ctf_lookup_by_symbol (cfp, idx)) == CTF_ERR)
>> -	{
>> -	if (ctf_errno (cfp) == EINVAL || ctf_errno (cfp) == ECTF_NOSYMTAB)
>> -	  break;	// Done, reach end of the section.
>> -	else
>> -	  continue;
>> -	}
>> -      const char *tname = ctf_type_name_raw (cfp, tid);
>> -      uint32_t kind = ctf_type_kind (cfp, tid);
>> -      address_class aclass;
>> -      domain_enum tdomain;
>> -      switch (kind)
>> -	{
>> -	  case CTF_K_STRUCT:
>> -	  case CTF_K_UNION:
>> -	  case CTF_K_ENUM:
>> -	    tdomain = STRUCT_DOMAIN;
>> -	    break;
>> -	  default:
>> -	    tdomain = VAR_DOMAIN;
>> -	    break;
>> -	}
>> +  ctf_psymtab_add_stt_obj (cfp, pst, of);
>> +  ctf_psymtab_add_stt_func (cfp, pst, of);
>>   
>> -      if (kind == CTF_K_FUNCTION)
>> -	aclass = LOC_STATIC;
>> -      else if (kind == CTF_K_CONST)
>> -	aclass = LOC_CONST;
>> -      else
>> -	aclass = LOC_TYPEDEF;
>> +  pst->end ();
>> +}
>>   
>> -      pst->add_psymbol (tname, false,
>> -			tdomain, aclass, -1,
>> -			psymbol_placement::STATIC,
>> -			0, language_c, partial_symtabs, of);
>> +/* Callback to build the psymtab for archive member NAME.  */
>> +
>> +static int
>> +build_ctf_archive_member (ctf_dict_t *ctf, const char *name, void *arg)
>> +{
>> +  struct ctf_per_tu_data *tup = (struct ctf_per_tu_data *) arg;
>> +  ctf_dict_t *parent = tup->fp;
>> +
>> +  if (strcmp (name, ".ctf") != 0)
>> +    ctf_import (ctf, parent);
>> +
>> +  if (info_verbose)
>> +    {
>> +      printf_filtered (_("Scanning archive member %s..."), name);
>> +      gdb_flush (gdb_stdout);
>>       }
>>   
>> -  pst->end ();
>> +  psymtab_storage *pss = tup->psf->get_partial_symtabs ().get ();
>> +  scan_partial_symbols (ctf, pss, tup, name);
>> +
>> +  return 0;
>>   }
>>   
>>   /* Read CTF debugging information from a BFD section.  This is
>> @@ -1579,6 +1619,7 @@ struct ctf_tid_and_type
>>   void
>>   elfctf_build_psymtabs (struct objfile *of)
>>   {
>> +  struct ctf_per_tu_data pcu;
>>     bfd *abfd = of->obfd;
>>     int err;
>>   
>> @@ -1593,10 +1634,18 @@ struct ctf_tid_and_type
>>   	   bfd_get_filename (abfd), ctf_errmsg (err));
>>     ctf_dict_key.emplace (of, fp);
>>   
>> +  pcu.fp = fp;
>> +  pcu.of = of;
>> +  pcu.arc = arc;
>> +
>>     psymbol_functions *psf = new psymbol_functions ();
>>     psymtab_storage *partial_symtabs = psf->get_partial_symtabs ().get ();
>>     of->qf.emplace_front (psf);
>> -  scan_partial_symbols (fp, partial_symtabs, of);
> By removing this call, 'partial_symtabs' (declared 2 lines above) is
> now unused and should also be removed.

Good catch. It will be removed.

> I hope those remarks / questions are useful.
Thanks for taking the time and your comments.

>
> Lancelot
>
>> +  pcu.psf = psf;
>> +
>> +  if (ctf_archive_iter (arc, build_ctf_archive_member, &pcu) < 0)
>> +    error (_("ctf_archive_iter failed in input file %s: - %s"),
>> +	   bfd_get_filename (abfd), ctf_errmsg (err));
>>   }
>>   
>>   #else
>> diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c
>> new file mode 100644
>> index 0000000..fe52b9e
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-1.c
>> @@ -0,0 +1,18 @@
>> +struct A;
>> +struct B
>> +{
>> +  int foo;
>> +  struct A *bar;
>> +};
>> +
>> +struct A
>> +{
>> +  long a;
>> +  struct B *foo;
>> +};
>> +
>> +static struct A *foo __attribute__((used));
>> +
>> +int main()
>> +{
>> +}
>> diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c
>> new file mode 100644
>> index 0000000..aa2d177
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-2.c
>> @@ -0,0 +1,16 @@
>> +struct B;
>> +struct A
>> +{
>> +  long a;
>> +  struct B *foo;
>> +  struct C *bar;
>> +};
>> +
>> +struct C
>> +{
>> +  struct B *foo;
>> +  int b;
>> +};
>> +
>> +static struct C *foo __attribute__((used));
>> +static struct A *bar __attribute__((used));
>> diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c
>> new file mode 100644
>> index 0000000..19947e8
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-3.c
>> @@ -0,0 +1,3 @@
>> +struct A { struct B *foo; };
>> +static struct A *a __attribute__((__used__));
>> +static struct A *conflicty __attribute__((__used__));
>> diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c
>> new file mode 100644
>> index 0000000..6e0c957
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic-4.c
>> @@ -0,0 +1,4 @@
>> +struct A { struct B *foo; };
>> +struct B { struct B *next; };
>> +static struct A *a __attribute__((__used__));
>> +static struct B *conflicty __attribute__((__used__));
>> diff --git a/gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp b/gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp
>> new file mode 100644
>> index 0000000..b6e640e
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.ctf/cross-tu-cyclic.exp
>> @@ -0,0 +1,43 @@
>> +# Copyright 2021 Free Software Foundation, Inc.
>> +
>> +# This program is free software; you can redistribute it and/or modify
>> +# it under the terms of the GNU General Public License as published by
>> +# the Free Software Foundation; either version 3 of the License, or
>> +# (at your option) any later version.
>> +#
>> +# This program is distributed in the hope that it will be useful,
>> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> +# GNU General Public License for more details.
>> +#
>> +# You should have received a copy of the GNU General Public License
>> +# along with this program.  If not, see <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!MhtIBI8EHfJeg3wdwWXoOjZ2I2QbUeJQxEbRWW6IUFtk_iT2CdzmXh-PEdoMmFZy$ >.
>> +
>> +# This file is a subset of ptype.exp written by Rob Savoye. (rob@cygnus.com)
>> +
>> +if [skip_ctf_tests] {
>> +    unsupported "no CTF debug format support, or CTF disabled in GDB"
>> +    return 0
>> +}
>> +
>> +standard_testfile cross-tu-cyclic-1.c  cross-tu-cyclic-2.c \
>> +	cross-tu-cyclic-3.c  cross-tu-cyclic-4.c
>> +
>> +# Using `-gt` generates full-fledged CTF debug information.
>> +set opts "additional_flags=-gt -Wl,--export-dynamic"
>> +if { [prepare_for_testing "failed to prepare" ${testfile} \
>> +	  [list $srcfile $srcfile2 $srcfile3 $srcfile4] \
>> +	  [list $opts nowarnings]] } {
>> +    return 0
>> +}
>> +
>> +# Create and source the file that provides information about the compiler
>> +# used to compile the test case.
>> +if [get_compiler_info] {
>> +    return -1
>> +}
>> +
>> +# Same thing with struct and union.
>> +gdb_test "ptype struct A" "type = struct A \{\[\r\n\]+\[ \t\]+struct B \\*foo;\[\r\n\]+\}.*" "ptype structure A"
>> +gdb_test "ptype struct B" "type = struct B \{\[\r\n\]+\[ \t\]+struct B \\*next;\[\r\n\]+\}.*" "ptype structure B"
>> +gdb_test "ptype struct C" "type = struct C \{\[\r\n\]+\[ \t\]+struct B \\*foo;\[\r\n\]+\[ \t\]+int b;\[\r\n\]+\}.*" "ptype structure C"
>> diff --git a/gdb/testsuite/gdb.ctf/ctf-a.c b/gdb/testsuite/gdb.ctf/ctf-a.c
>> new file mode 100644
>> index 0000000..9aa2a8f
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.ctf/ctf-a.c
>> @@ -0,0 +1,32 @@
>> +/* This test program is part of GDB, the GNU debugger.
>> +
>> +   Copyright 2021 Free Software Foundation, Inc.
>> +
>> +   This program is free software; you can redistribute it and/or modify
>> +   it under the terms of the GNU General Public License as published by
>> +   the Free Software Foundation; either version 3 of the License, or
>> +   (at your option) any later version.
>> +
>> +   This program is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> +   GNU General Public License for more details.
>> +
>> +   You should have received a copy of the GNU General Public License
>> +   along with this program.  If not, see <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!MhtIBI8EHfJeg3wdwWXoOjZ2I2QbUeJQxEbRWW6IUFtk_iT2CdzmXh-PEdoMmFZy$ >.  */
>> +
>> +#include "ctf-a.h"
>> +
>> +static struct A a __attribute__((used));
>> +
>> +extern struct C *foo ();
>> +extern int bar ();
>> +
>> +int main ()
>> +{
>> +  struct C *cp;
>> +  cp = foo ();
>> +  if (cp)
>> +    return bar ();
>> +  return 0;
>> +}
>> diff --git a/gdb/testsuite/gdb.ctf/ctf-a.h b/gdb/testsuite/gdb.ctf/ctf-a.h
>> new file mode 100644
>> index 0000000..297d740
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.ctf/ctf-a.h
>> @@ -0,0 +1,22 @@
>> +/* This test program is part of GDB, the GNU debugger.
>> +
>> +   Copyright 2021 Free Software Foundation, Inc.
>> +
>> +   This program is free software; you can redistribute it and/or modify
>> +   it under the terms of the GNU General Public License as published by
>> +   the Free Software Foundation; either version 3 of the License, or
>> +   (at your option) any later version.
>> +
>> +   This program is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> +   GNU General Public License for more details.
>> +
>> +   You should have received a copy of the GNU General Public License
>> +   along with this program.  If not, see <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!MhtIBI8EHfJeg3wdwWXoOjZ2I2QbUeJQxEbRWW6IUFtk_iT2CdzmXh-PEdoMmFZy$ >.  */
>> +
>> +struct A {
>> +  struct B *b;
>> +  struct A *next;
>> +};
>> +
>> diff --git a/gdb/testsuite/gdb.ctf/ctf-b.c b/gdb/testsuite/gdb.ctf/ctf-b.c
>> new file mode 100644
>> index 0000000..c3a8ce5
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.ctf/ctf-b.c
>> @@ -0,0 +1,25 @@
>> +/* This test program is part of GDB, the GNU debugger.
>> +
>> +   Copyright 2021 Free Software Foundation, Inc.
>> +
>> +   This program is free software; you can redistribute it and/or modify
>> +   it under the terms of the GNU General Public License as published by
>> +   the Free Software Foundation; either version 3 of the License, or
>> +   (at your option) any later version.
>> +
>> +   This program is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> +   GNU General Public License for more details.
>> +
>> +   You should have received a copy of the GNU General Public License
>> +   along with this program.  If not, see <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!MhtIBI8EHfJeg3wdwWXoOjZ2I2QbUeJQxEbRWW6IUFtk_iT2CdzmXh-PEdoMmFZy$ >.  */
>> +
>> +#include "ctf-b.h"
>> +
>> +static struct B b __attribute__((used));
>> +
>> +int bar ()
>> +{
>> +  return b.wombat;
>> +}
>> diff --git a/gdb/testsuite/gdb.ctf/ctf-b.h b/gdb/testsuite/gdb.ctf/ctf-b.h
>> new file mode 100644
>> index 0000000..9dbdd7d
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.ctf/ctf-b.h
>> @@ -0,0 +1,22 @@
>> +/* This test program is part of GDB, the GNU debugger.
>> +
>> +   Copyright 2021 Free Software Foundation, Inc.
>> +
>> +   This program is free software; you can redistribute it and/or modify
>> +   it under the terms of the GNU General Public License as published by
>> +   the Free Software Foundation; either version 3 of the License, or
>> +   (at your option) any later version.
>> +
>> +   This program is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> +   GNU General Public License for more details.
>> +
>> +   You should have received a copy of the GNU General Public License
>> +   along with this program.  If not, see <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!MhtIBI8EHfJeg3wdwWXoOjZ2I2QbUeJQxEbRWW6IUFtk_iT2CdzmXh-PEdoMmFZy$ >.  */
>> +
>> +struct B {
>> +  struct C *c;
>> +  int wombat;
>> +};
>> +
>> diff --git a/gdb/testsuite/gdb.ctf/ctf-c.c b/gdb/testsuite/gdb.ctf/ctf-c.c
>> new file mode 100644
>> index 0000000..b4051b3
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.ctf/ctf-c.c
>> @@ -0,0 +1,25 @@
>> +/* This test program is part of GDB, the GNU debugger.
>> +
>> +   Copyright 2021 Free Software Foundation, Inc.
>> +
>> +   This program is free software; you can redistribute it and/or modify
>> +   it under the terms of the GNU General Public License as published by
>> +   the Free Software Foundation; either version 3 of the License, or
>> +   (at your option) any later version.
>> +
>> +   This program is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> +   GNU General Public License for more details.
>> +
>> +   You should have received a copy of the GNU General Public License
>> +   along with this program.  If not, see <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!MhtIBI8EHfJeg3wdwWXoOjZ2I2QbUeJQxEbRWW6IUFtk_iT2CdzmXh-PEdoMmFZy$ >.  */
>> +
>> +#include "ctf-c.h"
>> +
>> +static struct C c __attribute__((used));
>> +
>> +struct C * foo ()
>> +{
>> +  return &c;
>> +}
>> diff --git a/gdb/testsuite/gdb.ctf/ctf-c.h b/gdb/testsuite/gdb.ctf/ctf-c.h
>> new file mode 100644
>> index 0000000..fb18157
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.ctf/ctf-c.h
>> @@ -0,0 +1,21 @@
>> +/* This test program is part of GDB, the GNU debugger.
>> +
>> +   Copyright 2021 Free Software Foundation, Inc.
>> +
>> +   This program is free software; you can redistribute it and/or modify
>> +   it under the terms of the GNU General Public License as published by
>> +   the Free Software Foundation; either version 3 of the License, or
>> +   (at your option) any later version.
>> +
>> +   This program is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> +   GNU General Public License for more details.
>> +
>> +   You should have received a copy of the GNU General Public License
>> +   along with this program.  If not, see <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!MhtIBI8EHfJeg3wdwWXoOjZ2I2QbUeJQxEbRWW6IUFtk_iT2CdzmXh-PEdoMmFZy$ >.  */
>> +
>> +struct C {
>> +  struct A *a;
>> +  int b;
>> +};
>> diff --git a/gdb/testsuite/gdb.ctf/multi.exp b/gdb/testsuite/gdb.ctf/multi.exp
>> new file mode 100644
>> index 0000000..973115e
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.ctf/multi.exp
>> @@ -0,0 +1,42 @@
>> +# Copyright 2021 Free Software Foundation, Inc.
>> +
>> +# This program is free software; you can redistribute it and/or modify
>> +# it under the terms of the GNU General Public License as published by
>> +# the Free Software Foundation; either version 3 of the License, or
>> +# (at your option) any later version.
>> +#
>> +# This program is distributed in the hope that it will be useful,
>> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> +# GNU General Public License for more details.
>> +#
>> +# You should have received a copy of the GNU General Public License
>> +# along with this program.  If not, see <https://urldefense.com/v3/__http://www.gnu.org/licenses/__;!!GqivPVa7Brio!MhtIBI8EHfJeg3wdwWXoOjZ2I2QbUeJQxEbRWW6IUFtk_iT2CdzmXh-PEdoMmFZy$ >.
>> +
>> +# This file is a subset of ptype.exp written by Rob Savoye. (rob@cygnus.com)
>> +
>> +if [skip_ctf_tests] {
>> +    unsupported "no CTF debug format support, or CTF disabled in GDB"
>> +    return 0
>> +}
>> +
>> +standard_testfile ctf-a.c ctf-b.c ctf-c.c
>> +
>> +# Using `-gt` generates full-fledged CTF debug information.
>> +set opts "additional_flags=-gt -Wl,--export-dynamic"
>> +if { [prepare_for_testing "failed to prepare" ${testfile} \
>> +	  [list $srcfile $srcfile2 $srcfile3] \
>> +	  [list $opts nowarnings]] } {
>> +    return 0
>> +}
>> +
>> +# Create and source the file that provides information about the compiler
>> +# used to compile the test case.
>> +if [get_compiler_info] {
>> +    return -1
>> +}
>> +
>> +# Same thing with struct and union.
>> +gdb_test "ptype struct A" "type = struct A \{\[\r\n\]+\[ \t\]+struct B \\*b;\[\r\n\]+\[ \t\]+struct A \\*next;\[\r\n\]+\}.*" "ptype structure A"
>> +gdb_test "ptype struct B" "type = struct B \{\[\r\n\]+\[ \t\]+struct C \\*c;\[\r\n\]+\[ \t\]+int \\wombat;\[\r\n\]+\}.*" "ptype structure B"
>> +gdb_test "ptype struct C" "type = struct C \{\[\r\n\]+\[ \t\]+struct A \\*a;\[\r\n\]+\[ \t\]+int b;\[\r\n\]+\}.*" "ptype structure C"
>> -- 
>> 1.8.3.1
>>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH V5] CTF: multi-CU and archive support
  2021-05-18  0:20 [PATCH V5] CTF: multi-CU and archive support Weimin Pan
  2021-05-25  0:52 ` [PING][PATCH " Wei-min Pan
  2021-06-10  0:40 ` [PATCH " Lancelot SIX
@ 2021-06-11 18:17 ` Tom Tromey
  2021-06-11 20:26   ` Wei-min Pan
  2 siblings, 1 reply; 11+ messages in thread
From: Tom Tromey @ 2021-06-11 18:17 UTC (permalink / raw)
  To: Weimin Pan via Gdb-patches

>>>>> ">" == Weimin Pan via Gdb-patches <gdb-patches@sourceware.org> writes:

>>  - Avoid calling ctf_dict_close more than once on a dictionary.]

>> +  ctf_ref (cfp);

I don't understand where the unref is done.
Maybe this just needs a comment or something, though?

Tom

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH V5] CTF: multi-CU and archive support
  2021-06-10  0:40 ` [PATCH " Lancelot SIX
  2021-06-10 21:15   ` Wei-min Pan
@ 2021-06-11 18:19   ` Tom Tromey
  2021-06-11 23:14     ` Lancelot SIX
  1 sibling, 1 reply; 11+ messages in thread
From: Tom Tromey @ 2021-06-11 18:19 UTC (permalink / raw)
  To: Lancelot SIX via Gdb-patches; +Cc: Weimin Pan, Lancelot SIX

>>>>> "Lancelot" == Lancelot SIX via Gdb-patches <gdb-patches@sourceware.org> writes:

Lancelot> Should be

Lancelot> if (sym != nullptr)

Agreed.

>> pst = new ctf_psymtab (name, partial_symtabs, objfile->per_bfd, 0);

Lancelot> I am a bit confused by this one.  As far as I can see, there is no way
Lancelot> it can ever be deleted.  Again, I am not so familiar with the code yet
Lancelot> so I might have missed something, but hopefully not.

psymtabs register themselves with a storage object.
This is unfortunate but it is how it has been done for a long time, and
nobody has bothered to clean it up.

Tom

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH V5] CTF: multi-CU and archive support
  2021-06-11 18:17 ` Tom Tromey
@ 2021-06-11 20:26   ` Wei-min Pan
  0 siblings, 0 replies; 11+ messages in thread
From: Wei-min Pan @ 2021-06-11 20:26 UTC (permalink / raw)
  To: Tom Tromey, Weimin Pan via Gdb-patches


On 6/11/2021 11:17 AM, Tom Tromey wrote:
>>>>>> ">" == Weimin Pan via Gdb-patches <gdb-patches@sourceware.org> writes:
>>>   - Avoid calling ctf_dict_close more than once on a dictionary.]
>>> +  ctf_ref (cfp);
> I don't understand where the unref is done.
> Maybe this just needs a comment or something, though?

OK, will add "Bump the refcount on the dict which will be closed by 
ctf_dict_key's dtor.".

>
> Tom

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH V5] CTF: multi-CU and archive support
  2021-06-10 21:15   ` Wei-min Pan
@ 2021-06-11 23:07     ` Lancelot SIX
  0 siblings, 0 replies; 11+ messages in thread
From: Lancelot SIX @ 2021-06-11 23:07 UTC (permalink / raw)
  To: Wei-min Pan; +Cc: gdb-patches

> Hi,
> 
> You can find the latest gcc patch series for CTF support, which is currently
> under review, here:
> 
> http://gcc.1065356.n8.nabble.com/PATCH-V9-0-7-Support-for-the-CTF-and-BTF-debug-formats-td1897109.html
> 
> Also please make sure to use a binutils version with CTF support.
> 

Hi,

Thanks for the pointer.

Now that I have a ctf-aware gcc, I can give a first try to the patch.

It looks like the flag to enable CTF generation (at least in this
version of the GCC patch set) is '-gctf', not '-gt'.

The '-gt' flag is currently used in the tests to detect if the
compiler supports CTF (in gdb/testsuite/lib/gdb.exp).  In the current
situation, tests are skipped with GCC master + CTF.  We might want to
wait for GCC to settle on the flag, and update tests codebase as well as
this patch.

> 
> I believe  the psymtab_discarder's dtor should take care of discarding all
> built partial
> symbol tables. So I'm not sure if this is a CTF specific issue.
> 

It is taken care of by psymtab_storage::~psymtab_storage which is
eventually triggered by the dtor of objfile.  I did not dig enough
before sending the email.  Sorry for that.

> One way to avoid dealing with either the storage or dtor issue is to
> declare:
> 
>         struct ctf_context context;
> 
> in struct ctf_psymtab.

Yes, this would work.  However, considering what I missed with the
memory management of the psymtab and given that ctf_context is a POD
type, everything should properly come down with the dtor of objfile.  So
after reconsidering I believe your proposition should works.

Lancelot.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH V5] CTF: multi-CU and archive support
  2021-06-11 18:19   ` Tom Tromey
@ 2021-06-11 23:14     ` Lancelot SIX
  0 siblings, 0 replies; 11+ messages in thread
From: Lancelot SIX @ 2021-06-11 23:14 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Lancelot SIX via Gdb-patches, Weimin Pan

On Fri, Jun 11, 2021 at 12:19:05PM -0600, Tom Tromey wrote:
> >>>>> "Lancelot" == Lancelot SIX via Gdb-patches <gdb-patches@sourceware.org> writes:
> 
> Lancelot> Should be
> 
> Lancelot> if (sym != nullptr)
> 
> Agreed.
> 
> >> pst = new ctf_psymtab (name, partial_symtabs, objfile->per_bfd, 0);
> 
> Lancelot> I am a bit confused by this one.  As far as I can see, there is no way
> Lancelot> it can ever be deleted.  Again, I am not so familiar with the code yet
> Lancelot> so I might have missed something, but hopefully not.
> 
> psymtabs register themselves with a storage object.
> This is unfortunate but it is how it has been done for a long time, and
> nobody has bothered to clean it up.
> 
> Tom

Thanks for the info.  This is something I missed initially.  “naked
new”s without obvious deletes tend to raise some alarms when I read
code…

Lancelot.

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2021-06-11 23:14 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-18  0:20 [PATCH V5] CTF: multi-CU and archive support Weimin Pan
2021-05-25  0:52 ` [PING][PATCH " Wei-min Pan
2021-06-02  0:05   ` [PING 2][PATCH " Wei-min Pan
2021-06-09  0:37     ` [PING 3][PATCH " Wei-min Pan
2021-06-10  0:40 ` [PATCH " Lancelot SIX
2021-06-10 21:15   ` Wei-min Pan
2021-06-11 23:07     ` Lancelot SIX
2021-06-11 18:19   ` Tom Tromey
2021-06-11 23:14     ` Lancelot SIX
2021-06-11 18:17 ` Tom Tromey
2021-06-11 20:26   ` Wei-min Pan

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).