[11/14] Split type_unit_group

Message ID 20200215165444.32653-12-tom@tromey.com
State New
Headers show
Series
  • Share DWARF partial symtabs between objfiles
Related show

Commit Message

Tom Tromey Feb. 15, 2020, 4:54 p.m.
type_unit_group has links to the compunit_symtab and other symtabs.
However, once this object is shared across objfiles, this will no
longer be ok.

This patch introduces a new type_unit_unshareable and arranges to
store a map from type unit groups to type_unit_unshareable objects on
the DWARF unshareable object.

2020-02-15  Tom Tromey  <tom@tromey.com>

	* dwarf2/read.h (struct type_unit_unshareable): New.
	(struct dwarf2_unshareable) <type_units>: New member.
	* dwarf2/read.c (struct type_unit_group) <compunit_symtab,
	num_symtabs, symtabs>: Remove; move to type_unit_unshareable.
	(get_type_unit_group_unshareable): New function.
	(process_full_type_unit, dwarf2_cu::setup_type_unit_groups)
	(dwarf2_cu::setup_type_unit_groups): Use type_unit_unshareable.
---
 gdb/ChangeLog     | 10 ++++++++
 gdb/dwarf2/read.c | 65 +++++++++++++++++++++++++----------------------
 gdb/dwarf2/read.h | 30 ++++++++++++++++++++++
 3 files changed, 74 insertions(+), 31 deletions(-)

-- 
2.17.2

Comments

Luis Machado Feb. 18, 2020, 12:08 p.m. | #1
On 2/15/20 1:54 PM, Tom Tromey wrote:
> type_unit_group has links to the compunit_symtab and other symtabs.

> However, once this object is shared across objfiles, this will no

> longer be ok.

> 

> This patch introduces a new type_unit_unshareable and arranges to

> store a map from type unit groups to type_unit_unshareable objects on

> the DWARF unshareable object.

> 

> 2020-02-15  Tom Tromey  <tom@tromey.com>

> 

> 	* dwarf2/read.h (struct type_unit_unshareable): New.

> 	(struct dwarf2_unshareable) <type_units>: New member.

> 	* dwarf2/read.c (struct type_unit_group) <compunit_symtab,

> 	num_symtabs, symtabs>: Remove; move to type_unit_unshareable.

> 	(get_type_unit_group_unshareable): New function.

> 	(process_full_type_unit, dwarf2_cu::setup_type_unit_groups)

> 	(dwarf2_cu::setup_type_unit_groups): Use type_unit_unshareable.

> ---

>   gdb/ChangeLog     | 10 ++++++++

>   gdb/dwarf2/read.c | 65 +++++++++++++++++++++++++----------------------

>   gdb/dwarf2/read.h | 30 ++++++++++++++++++++++

>   3 files changed, 74 insertions(+), 31 deletions(-)

> 

> diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c

> index f86034f2273..d1c5bee1109 100644

> --- a/gdb/dwarf2/read.c

> +++ b/gdb/dwarf2/read.c

> @@ -580,27 +580,8 @@ struct type_unit_group

>        and is deleted afterwards and not used again.  */

>     std::vector<signatured_type *> *tus;

>   

> -  /* The compunit symtab.

> -     Type units in a group needn't all be defined in the same source file,

> -     so we create an essentially anonymous symtab as the compunit symtab.  */

> -  struct compunit_symtab *compunit_symtab;

> -

>     /* The data used to construct the hash key.  */

>     struct stmt_list_hash hash;

> -

> -  /* The number of symtabs from the line header.

> -     The value here must match line_header.num_file_names.  */

> -  unsigned int num_symtabs;

> -

> -  /* The symbol tables for this TU (obtained from the files listed in

> -     DW_AT_stmt_list).

> -     WARNING: The order of entries here must match the order of entries

> -     in the line header.  After the first TU using this type_unit_group, the

> -     line header for the subsequent TUs is recreated from this.  This is done

> -     because we need to use the same symtabs for each TU using the same

> -     DW_AT_stmt_list value.  Also note that symtabs may be repeated here,

> -     there's no guarantee the line header doesn't have duplicate entries.  */

> -  struct symtab **symtabs;

>   };

>   

>   /* These sections are what may appear in a (real or virtual) DWO file.  */

> @@ -9507,6 +9488,22 @@ rust_union_quirks (struct dwarf2_cu *cu)

>     cu->rust_unions.clear ();

>   }

>   

> +/* Get the type_unit_unshareable corresponding to TU_GROUP.  If one

> +   does not exist, create it.  */

> +

> +static type_unit_unshareable *

> +get_type_unit_group_unshareable (dwarf2_per_objfile *dwarf2_per_objfile,

> +				 type_unit_group *tu_group)

> +{

> +  auto iter = dwarf2_per_objfile->unshareable->type_units.find (tu_group);

> +  if (iter != dwarf2_per_objfile->unshareable->type_units.end ())

> +    return iter->second.get ();

> +  std::unique_ptr<type_unit_unshareable> uniq (new type_unit_unshareable);

> +  type_unit_unshareable *result = uniq.get ();

> +  dwarf2_per_objfile->unshareable->type_units[tu_group] = std::move (uniq);

> +  return result;

> +}

> +

>   /* Return the symtab for PER_CU.  This works properly regardless of

>      whether we're using the index or psymtabs.  */

>   

> @@ -9776,11 +9773,14 @@ process_full_type_unit (struct dwarf2_per_cu_data *per_cu,

>        If this is the first TU to use this symtab, complete the construction

>        of it with end_expandable_symtab.  Otherwise, complete the addition of

>        this TU's symbols to the existing symtab.  */

> -  if (sig_type->type_unit_group->compunit_symtab == NULL)

> +  type_unit_unshareable *tu_unshare

> +    = get_type_unit_group_unshareable (dwarf2_per_objfile,

> +				       sig_type->type_unit_group);

> +  if (tu_unshare->compunit_symtab == NULL)

>       {

>         buildsym_compunit *builder = cu->get_builder ();

>         cust = builder->end_expandable_symtab (0, SECT_OFF_TEXT (objfile));

> -      sig_type->type_unit_group->compunit_symtab = cust;

> +      tu_unshare->compunit_symtab = cust;

>   

>         if (cust != NULL)

>   	{

> @@ -9796,7 +9796,7 @@ process_full_type_unit (struct dwarf2_per_cu_data *per_cu,

>     else

>       {

>         cu->get_builder ()->augment_type_symtab ();

> -      cust = sig_type->type_unit_group->compunit_symtab;

> +      cust = tu_unshare->compunit_symtab;

>       }

>   

>     gdb::optional<compunit_symtab *> &symtab

> @@ -10930,7 +10930,10 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)

>        do it again, we could fake it and just recreate the part we need

>        (file name,index -> symtab mapping).  If data shows this optimization

>        is useful we can do it then.  */

> -  first_time = tu_group->compunit_symtab == NULL;

> +  struct dwarf2_per_objfile *dwarf2_per_objfile = per_cu->dwarf2_per_objfile;

> +  type_unit_unshareable *tu_unshare

> +    = get_type_unit_group_unshareable (dwarf2_per_objfile, tu_group);

> +  first_time = tu_unshare->compunit_symtab == NULL;

>   

>     /* We have to handle the case of both a missing DW_AT_stmt_list or bad

>        debug info.  */

> @@ -10946,9 +10949,9 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)

>   	start_symtab ("", NULL, 0);

>         else

>   	{

> -	  gdb_assert (tu_group->symtabs == NULL);

> +	  gdb_assert (tu_unshare->symtabs == NULL);

>   	  gdb_assert (m_builder == nullptr);

> -	  struct compunit_symtab *cust = tu_group->compunit_symtab;

> +	  struct compunit_symtab *cust = tu_unshare->compunit_symtab;

>   	  m_builder.reset (new struct buildsym_compunit

>   			   (COMPUNIT_OBJFILE (cust), "",

>   			    COMPUNIT_DIRNAME (cust),

> @@ -10970,9 +10973,9 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)

>   	 process_full_type_unit still needs to know if this is the first

>   	 time.  */

>   

> -      tu_group->num_symtabs = line_header->file_names_size ();

> -      tu_group->symtabs = XNEWVEC (struct symtab *,

> -				   line_header->file_names_size ());

> +      tu_unshare->num_symtabs = line_header->file_names_size ();

> +      tu_unshare->symtabs = XNEWVEC (struct symtab *,

> +				     line_header->file_names_size ());

>   

>         auto &file_names = line_header->file_names ();

>         for (i = 0; i < file_names.size (); ++i)

> @@ -10993,13 +10996,13 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)

>   	    }

>   

>   	  fe.symtab = b->get_current_subfile ()->symtab;

> -	  tu_group->symtabs[i] = fe.symtab;

> +	  tu_unshare->symtabs[i] = fe.symtab;

>   	}

>       }

>     else

>       {

>         gdb_assert (m_builder == nullptr);

> -      struct compunit_symtab *cust = tu_group->compunit_symtab;

> +      struct compunit_symtab *cust = tu_unshare->compunit_symtab;

>         m_builder.reset (new struct buildsym_compunit

>   		       (COMPUNIT_OBJFILE (cust), "",

>   			COMPUNIT_DIRNAME (cust),

> @@ -11010,7 +11013,7 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)

>         for (i = 0; i < file_names.size (); ++i)

>   	{

>   	  file_entry &fe = file_names[i];

> -	  fe.symtab = tu_group->symtabs[i];

> +	  fe.symtab = tu_unshare->symtabs[i];

>   	}

>       }

>   

> diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h

> index bef37e969d3..8b2e8703aa0 100644

> --- a/gdb/dwarf2/read.h

> +++ b/gdb/dwarf2/read.h

> @@ -47,6 +47,7 @@ struct dwarf2_per_cu_data;

>   struct mapped_index;

>   struct mapped_debug_names;

>   struct signatured_type;

> +struct type_unit_group;

>   

>   /* One item on the queue of compilation units to read in full symbols

>      for.  */

> @@ -66,6 +67,30 @@ struct dwarf2_queue_item

>     enum language pretend_language;

>   };

>   

> +/* This is the per-objfile data associated with a type_unit_group.  */

> +

> +struct type_unit_unshareable

> +{

> +  /* The compunit symtab.

> +     Type units in a group needn't all be defined in the same source file,

> +     so we create an essentially anonymous symtab as the compunit symtab.  */

> +  struct compunit_symtab *compunit_symtab = nullptr;

> +

> +  /* The number of symtabs from the line header.

> +     The value here must match line_header.num_file_names.  */

> +  unsigned int num_symtabs = 0;

> +

> +  /* The symbol tables for this TU (obtained from the files listed in

> +     DW_AT_stmt_list).

> +     WARNING: The order of entries here must match the order of entries

> +     in the line header.  After the first TU using this type_unit_group, the

> +     line header for the subsequent TUs is recreated from this.  This is done

> +     because we need to use the same symtabs for each TU using the same

> +     DW_AT_stmt_list value.  Also note that symtabs may be repeated here,

> +     there's no guarantee the line header doesn't have duplicate entries.  */


Does something need to be adjusted in the comments for "struct 
type_unit_unshareable" now that we've split these fields from the bigger 
type_unit_group struct?

> +  struct symtab **symtabs = nullptr;

> +};

> +

>   /* Some DWARF data cannot (currently) be shared across objfiles.  Such

>      data is stored in this object.

>   

> @@ -86,6 +111,11 @@ struct dwarf2_unshareable

>     /* Hold the corresponding compunit_symtab for each CU or TU.  This

>        is indexed by dwarf2_per_cu_data::index.  */

>     std::vector<gdb::optional<compunit_symtab *>> symtabs;

> +

> +  /* Map from a type unit group to the corresponding unshared

> +     structure.  */

> +  std::unordered_map<type_unit_group *, std::unique_ptr<type_unit_unshareable>>

> +    type_units;

>   };

>   

>   /* Collection of data recorded per objfile.

>
Tom Tromey Feb. 22, 2020, 12:40 a.m. | #2
>>>>> "Luis" == Luis Machado <luis.machado@linaro.org> writes:


>> +  /* The symbol tables for this TU (obtained from the files listed in

>> +     DW_AT_stmt_list).

>> +     WARNING: The order of entries here must match the order of entries

>> +     in the line header.  After the first TU using this type_unit_group, the

>> +     line header for the subsequent TUs is recreated from this.  This is done

>> +     because we need to use the same symtabs for each TU using the same

>> +     DW_AT_stmt_list value.  Also note that symtabs may be repeated here,

>> +     there's no guarantee the line header doesn't have duplicate entries.  */


Luis> Does something need to be adjusted in the comments for "struct
Luis> type_unit_unshareable" now that we've split these fields from the
Luis> bigger type_unit_group struct?

I think this all remained the same.

Tom

Patch

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index f86034f2273..d1c5bee1109 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -580,27 +580,8 @@  struct type_unit_group
      and is deleted afterwards and not used again.  */
   std::vector<signatured_type *> *tus;
 
-  /* The compunit symtab.
-     Type units in a group needn't all be defined in the same source file,
-     so we create an essentially anonymous symtab as the compunit symtab.  */
-  struct compunit_symtab *compunit_symtab;
-
   /* The data used to construct the hash key.  */
   struct stmt_list_hash hash;
-
-  /* The number of symtabs from the line header.
-     The value here must match line_header.num_file_names.  */
-  unsigned int num_symtabs;
-
-  /* The symbol tables for this TU (obtained from the files listed in
-     DW_AT_stmt_list).
-     WARNING: The order of entries here must match the order of entries
-     in the line header.  After the first TU using this type_unit_group, the
-     line header for the subsequent TUs is recreated from this.  This is done
-     because we need to use the same symtabs for each TU using the same
-     DW_AT_stmt_list value.  Also note that symtabs may be repeated here,
-     there's no guarantee the line header doesn't have duplicate entries.  */
-  struct symtab **symtabs;
 };
 
 /* These sections are what may appear in a (real or virtual) DWO file.  */
@@ -9507,6 +9488,22 @@  rust_union_quirks (struct dwarf2_cu *cu)
   cu->rust_unions.clear ();
 }
 
+/* Get the type_unit_unshareable corresponding to TU_GROUP.  If one
+   does not exist, create it.  */
+
+static type_unit_unshareable *
+get_type_unit_group_unshareable (dwarf2_per_objfile *dwarf2_per_objfile,
+				 type_unit_group *tu_group)
+{
+  auto iter = dwarf2_per_objfile->unshareable->type_units.find (tu_group);
+  if (iter != dwarf2_per_objfile->unshareable->type_units.end ())
+    return iter->second.get ();
+  std::unique_ptr<type_unit_unshareable> uniq (new type_unit_unshareable);
+  type_unit_unshareable *result = uniq.get ();
+  dwarf2_per_objfile->unshareable->type_units[tu_group] = std::move (uniq);
+  return result;
+}
+
 /* Return the symtab for PER_CU.  This works properly regardless of
    whether we're using the index or psymtabs.  */
 
@@ -9776,11 +9773,14 @@  process_full_type_unit (struct dwarf2_per_cu_data *per_cu,
      If this is the first TU to use this symtab, complete the construction
      of it with end_expandable_symtab.  Otherwise, complete the addition of
      this TU's symbols to the existing symtab.  */
-  if (sig_type->type_unit_group->compunit_symtab == NULL)
+  type_unit_unshareable *tu_unshare
+    = get_type_unit_group_unshareable (dwarf2_per_objfile,
+				       sig_type->type_unit_group);
+  if (tu_unshare->compunit_symtab == NULL)
     {
       buildsym_compunit *builder = cu->get_builder ();
       cust = builder->end_expandable_symtab (0, SECT_OFF_TEXT (objfile));
-      sig_type->type_unit_group->compunit_symtab = cust;
+      tu_unshare->compunit_symtab = cust;
 
       if (cust != NULL)
 	{
@@ -9796,7 +9796,7 @@  process_full_type_unit (struct dwarf2_per_cu_data *per_cu,
   else
     {
       cu->get_builder ()->augment_type_symtab ();
-      cust = sig_type->type_unit_group->compunit_symtab;
+      cust = tu_unshare->compunit_symtab;
     }
 
   gdb::optional<compunit_symtab *> &symtab
@@ -10930,7 +10930,10 @@  dwarf2_cu::setup_type_unit_groups (struct die_info *die)
      do it again, we could fake it and just recreate the part we need
      (file name,index -> symtab mapping).  If data shows this optimization
      is useful we can do it then.  */
-  first_time = tu_group->compunit_symtab == NULL;
+  struct dwarf2_per_objfile *dwarf2_per_objfile = per_cu->dwarf2_per_objfile;
+  type_unit_unshareable *tu_unshare
+    = get_type_unit_group_unshareable (dwarf2_per_objfile, tu_group);
+  first_time = tu_unshare->compunit_symtab == NULL;
 
   /* We have to handle the case of both a missing DW_AT_stmt_list or bad
      debug info.  */
@@ -10946,9 +10949,9 @@  dwarf2_cu::setup_type_unit_groups (struct die_info *die)
 	start_symtab ("", NULL, 0);
       else
 	{
-	  gdb_assert (tu_group->symtabs == NULL);
+	  gdb_assert (tu_unshare->symtabs == NULL);
 	  gdb_assert (m_builder == nullptr);
-	  struct compunit_symtab *cust = tu_group->compunit_symtab;
+	  struct compunit_symtab *cust = tu_unshare->compunit_symtab;
 	  m_builder.reset (new struct buildsym_compunit
 			   (COMPUNIT_OBJFILE (cust), "",
 			    COMPUNIT_DIRNAME (cust),
@@ -10970,9 +10973,9 @@  dwarf2_cu::setup_type_unit_groups (struct die_info *die)
 	 process_full_type_unit still needs to know if this is the first
 	 time.  */
 
-      tu_group->num_symtabs = line_header->file_names_size ();
-      tu_group->symtabs = XNEWVEC (struct symtab *,
-				   line_header->file_names_size ());
+      tu_unshare->num_symtabs = line_header->file_names_size ();
+      tu_unshare->symtabs = XNEWVEC (struct symtab *,
+				     line_header->file_names_size ());
 
       auto &file_names = line_header->file_names ();
       for (i = 0; i < file_names.size (); ++i)
@@ -10993,13 +10996,13 @@  dwarf2_cu::setup_type_unit_groups (struct die_info *die)
 	    }
 
 	  fe.symtab = b->get_current_subfile ()->symtab;
-	  tu_group->symtabs[i] = fe.symtab;
+	  tu_unshare->symtabs[i] = fe.symtab;
 	}
     }
   else
     {
       gdb_assert (m_builder == nullptr);
-      struct compunit_symtab *cust = tu_group->compunit_symtab;
+      struct compunit_symtab *cust = tu_unshare->compunit_symtab;
       m_builder.reset (new struct buildsym_compunit
 		       (COMPUNIT_OBJFILE (cust), "",
 			COMPUNIT_DIRNAME (cust),
@@ -11010,7 +11013,7 @@  dwarf2_cu::setup_type_unit_groups (struct die_info *die)
       for (i = 0; i < file_names.size (); ++i)
 	{
 	  file_entry &fe = file_names[i];
-	  fe.symtab = tu_group->symtabs[i];
+	  fe.symtab = tu_unshare->symtabs[i];
 	}
     }
 
diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h
index bef37e969d3..8b2e8703aa0 100644
--- a/gdb/dwarf2/read.h
+++ b/gdb/dwarf2/read.h
@@ -47,6 +47,7 @@  struct dwarf2_per_cu_data;
 struct mapped_index;
 struct mapped_debug_names;
 struct signatured_type;
+struct type_unit_group;
 
 /* One item on the queue of compilation units to read in full symbols
    for.  */
@@ -66,6 +67,30 @@  struct dwarf2_queue_item
   enum language pretend_language;
 };
 
+/* This is the per-objfile data associated with a type_unit_group.  */
+
+struct type_unit_unshareable
+{
+  /* The compunit symtab.
+     Type units in a group needn't all be defined in the same source file,
+     so we create an essentially anonymous symtab as the compunit symtab.  */
+  struct compunit_symtab *compunit_symtab = nullptr;
+
+  /* The number of symtabs from the line header.
+     The value here must match line_header.num_file_names.  */
+  unsigned int num_symtabs = 0;
+
+  /* The symbol tables for this TU (obtained from the files listed in
+     DW_AT_stmt_list).
+     WARNING: The order of entries here must match the order of entries
+     in the line header.  After the first TU using this type_unit_group, the
+     line header for the subsequent TUs is recreated from this.  This is done
+     because we need to use the same symtabs for each TU using the same
+     DW_AT_stmt_list value.  Also note that symtabs may be repeated here,
+     there's no guarantee the line header doesn't have duplicate entries.  */
+  struct symtab **symtabs = nullptr;
+};
+
 /* Some DWARF data cannot (currently) be shared across objfiles.  Such
    data is stored in this object.
 
@@ -86,6 +111,11 @@  struct dwarf2_unshareable
   /* Hold the corresponding compunit_symtab for each CU or TU.  This
      is indexed by dwarf2_per_cu_data::index.  */
   std::vector<gdb::optional<compunit_symtab *>> symtabs;
+
+  /* Map from a type unit group to the corresponding unshared
+     structure.  */
+  std::unordered_map<type_unit_group *, std::unique_ptr<type_unit_unshareable>>
+    type_units;
 };
 
 /* Collection of data recorded per objfile.