Change how dwarf2_per_cu_data is deleted
authorTom Tromey <tromey@adacore.com>
Mon, 17 May 2021 18:55:18 +0000 (12:55 -0600)
committerTom Tromey <tromey@adacore.com>
Mon, 17 May 2021 19:01:42 +0000 (13:01 -0600)
Address sanitizer pointed out that the patch to use 'delete' for
dwarf2_per_cu_data introduced a bug -- now it is possible to delete a
signatured_type using a pointer to its base class.

This patch fixes the problem by introducing a deleter and a unique_ptr
specialization.  A virtual destructor would be more ordinary here, but
it seemed wasteful to add a vtable just for this purpose.  If virtual
methods are ever needed here, we can revisit this.

2021-05-17  Tom Tromey  <tromey@adacore.com>

* dwarf2/read.h (struct dwarf2_per_cu_data_deleter: New.
(dwarf2_per_cu_data_up): New typedef.
(struct dwarf2_per_bfd) <allocate_per_cu>: Change return type.
<all_comp_units>: Use dwarf2_per_cu_data_up.
* dwarf2/read.c (dwarf2_per_cu_data::operator()): New function.
(dwarf2_per_bfd::allocate_per_cu): Return dwarf2_per_cu_data_up.
(create_cu_from_index_list): Likewise.
(create_signatured_type_table_from_index)
(create_cus_from_debug_names_list, add_type_unit)
(read_comp_units_from_section): Update.
(dwarf2_find_containing_comp_unit): Change type of all_comp_units.
(run_test): Update.

gdb/ChangeLog
gdb/dwarf2/read.c
gdb/dwarf2/read.h

index b4fd2bb69f01ff6fc46b0e84199a8dc591d5299a..b2743646511ae88264eb674dd3ec32c007b92f81 100644 (file)
@@ -1,3 +1,18 @@
+2021-05-17  Tom Tromey  <tromey@adacore.com>
+
+       * dwarf2/read.h (struct dwarf2_per_cu_data_deleter: New.
+       (dwarf2_per_cu_data_up): New typedef.
+       (struct dwarf2_per_bfd) <allocate_per_cu>: Change return type.
+       <all_comp_units>: Use dwarf2_per_cu_data_up.
+       * dwarf2/read.c (dwarf2_per_cu_data::operator()): New function.
+       (dwarf2_per_bfd::allocate_per_cu): Return dwarf2_per_cu_data_up.
+       (create_cu_from_index_list): Likewise.
+       (create_signatured_type_table_from_index)
+       (create_cus_from_debug_names_list, add_type_unit)
+       (read_comp_units_from_section): Update.
+       (dwarf2_find_containing_comp_unit): Change type of all_comp_units.
+       (run_test): Update.
+
 2021-05-17  Tom Tromey  <tom@tromey.com>
 
        * dwarf2/read.c (tu_abbrev_offset::operator<): New method.
index f1bb9b2f3df341e5c30bc18a3c5cab4efa1a7250..b3b8f1b830dbe27acb4748180e2ff72124ddec82 100644 (file)
@@ -1760,6 +1760,17 @@ dwarf2_queue_item::~dwarf2_queue_item ()
     }
 }
 
+/* See dwarf2/read.h.  */
+
+void
+dwarf2_per_cu_data_deleter::operator() (dwarf2_per_cu_data *data)
+{
+  if (data->is_debug_types)
+    delete static_cast<signatured_type *> (data);
+  else
+    delete data;
+}
+
 /* The return type of find_file_and_directory.  Note, the enclosed
    string pointers are only valid while this object is valid.  */
 
@@ -2522,10 +2533,10 @@ dw2_instantiate_symtab (dwarf2_per_cu_data *per_cu,
 
 /* See read.h.  */
 
-std::unique_ptr<dwarf2_per_cu_data>
+dwarf2_per_cu_data_up
 dwarf2_per_bfd::allocate_per_cu ()
 {
-  std::unique_ptr<dwarf2_per_cu_data> result (new dwarf2_per_cu_data);
+  dwarf2_per_cu_data_up result (new dwarf2_per_cu_data);
   result->per_bfd = this;
   result->index = m_num_psymtabs++;
   return result;
@@ -2546,13 +2557,13 @@ dwarf2_per_bfd::allocate_signatured_type ()
 /* Return a new dwarf2_per_cu_data allocated on the per-bfd
    obstack, and constructed with the specified field values.  */
 
-static std::unique_ptr<dwarf2_per_cu_data>
+static dwarf2_per_cu_data_up
 create_cu_from_index_list (dwarf2_per_bfd *per_bfd,
                           struct dwarf2_section_info *section,
                           int is_dwz,
                           sect_offset sect_off, ULONGEST length)
 {
-  std::unique_ptr<dwarf2_per_cu_data> the_cu = per_bfd->allocate_per_cu ();
+  dwarf2_per_cu_data_up the_cu = per_bfd->allocate_per_cu ();
   the_cu->sect_off = sect_off;
   the_cu->length = length;
   the_cu->section = section;
@@ -2580,7 +2591,7 @@ create_cus_from_index_list (dwarf2_per_bfd *per_bfd,
       ULONGEST length = extract_unsigned_integer (cu_list + 8, 8, BFD_ENDIAN_LITTLE);
       cu_list += 2 * 8;
 
-      std::unique_ptr<dwarf2_per_cu_data> per_cu
+      dwarf2_per_cu_data_up per_cu
        = create_cu_from_index_list (per_bfd, section, is_dwz, sect_off,
                                     length);
       per_bfd->all_comp_units.push_back (std::move (per_cu));
@@ -2647,7 +2658,7 @@ create_signatured_type_table_from_index
       slot = htab_find_slot (sig_types_hash.get (), sig_type.get (), INSERT);
       *slot = sig_type.get ();
 
-      per_bfd->all_comp_units.push_back (std::move (sig_type));
+      per_bfd->all_comp_units.emplace_back (sig_type.release ());
     }
 
   per_bfd->signatured_types = std::move (sig_types_hash);
@@ -2699,7 +2710,7 @@ create_signatured_type_table_from_debug_names
       slot = htab_find_slot (sig_types_hash.get (), sig_type.get (), INSERT);
       *slot = sig_type.get ();
 
-      per_objfile->per_bfd->all_comp_units.push_back (std::move (sig_type));
+      per_objfile->per_bfd->all_comp_units.emplace_back (sig_type.release ());
     }
 
   per_objfile->per_bfd->signatured_types = std::move (sig_types_hash);
@@ -4930,7 +4941,7 @@ create_cus_from_debug_names_list (dwarf2_per_bfd *per_bfd,
             of the next CU as end of this CU.  We create the CUs here with
             length 0, and in cutu_reader::cutu_reader we'll fill in the
             actual length.  */
-         std::unique_ptr<dwarf2_per_cu_data> per_cu
+         dwarf2_per_cu_data_up per_cu
            = create_cu_from_index_list (per_bfd, &section, is_dwz,
                                         sect_off, 0);
          per_bfd->all_comp_units.push_back (std::move (per_cu));
@@ -4955,7 +4966,7 @@ create_cus_from_debug_names_list (dwarf2_per_bfd *per_bfd,
       if (i >= 1)
        {
          const ULONGEST length = sect_off_next - sect_off_prev;
-         std::unique_ptr<dwarf2_per_cu_data> per_cu
+         dwarf2_per_cu_data_up per_cu
            = create_cu_from_index_list (per_bfd, &section, is_dwz,
                                         sect_off_prev, length);
          per_bfd->all_comp_units.push_back (std::move (per_cu));
@@ -6132,7 +6143,8 @@ add_type_unit (dwarf2_per_objfile *per_objfile, ULONGEST sig, void **slot)
 
   per_objfile->resize_symtabs ();
 
-  per_objfile->per_bfd->all_comp_units.push_back (std::move (sig_type_holder));
+  per_objfile->per_bfd->all_comp_units.emplace_back
+    (sig_type_holder.release ());
   sig_type->signature = sig;
   sig_type->is_debug_types = 1;
   if (per_objfile->per_bfd->using_index)
@@ -7707,7 +7719,7 @@ read_comp_units_from_section (dwarf2_per_objfile *per_objfile,
 
   while (info_ptr < section->buffer + section->size)
     {
-      std::unique_ptr<dwarf2_per_cu_data> this_cu;
+      dwarf2_per_cu_data_up this_cu;
 
       sect_offset sect_off = (sect_offset) (info_ptr - section->buffer);
 
@@ -7728,7 +7740,7 @@ read_comp_units_from_section (dwarf2_per_objfile *per_objfile,
          signatured_type *sig_ptr = sig_type.get ();
          sig_type->signature = cu_header.signature;
          sig_type->type_offset_in_tu = cu_header.type_cu_offset_in_tu;
-         this_cu = std::move (sig_type);
+         this_cu.reset (sig_type.release ());
 
          void **slot = htab_find_slot (types_htab.get (), sig_ptr, INSERT);
          gdb_assert (slot != nullptr);
@@ -24577,7 +24589,7 @@ static int
 dwarf2_find_containing_comp_unit
   (sect_offset sect_off,
    unsigned int offset_in_dwz,
-   const std::vector<std::unique_ptr<dwarf2_per_cu_data>> &all_comp_units)
+   const std::vector<dwarf2_per_cu_data_up> &all_comp_units)
 {
   int low, high;
 
@@ -24643,13 +24655,13 @@ namespace find_containing_comp_unit {
 static void
 run_test ()
 {
-  std::unique_ptr<dwarf2_per_cu_data> one (new dwarf2_per_cu_data);
+  dwarf2_per_cu_data_up one (new dwarf2_per_cu_data);
   dwarf2_per_cu_data *one_ptr = one.get ();
-  std::unique_ptr<dwarf2_per_cu_data> two (new dwarf2_per_cu_data);
+  dwarf2_per_cu_data_up two (new dwarf2_per_cu_data);
   dwarf2_per_cu_data *two_ptr = two.get ();
-  std::unique_ptr<dwarf2_per_cu_data> three (new dwarf2_per_cu_data);
+  dwarf2_per_cu_data_up three (new dwarf2_per_cu_data);
   dwarf2_per_cu_data *three_ptr = three.get ();
-  std::unique_ptr<dwarf2_per_cu_data> four (new dwarf2_per_cu_data);
+  dwarf2_per_cu_data_up four (new dwarf2_per_cu_data);
   dwarf2_per_cu_data *four_ptr = four.get ();
 
   one->length = 5;
@@ -24662,7 +24674,7 @@ run_test ()
   four->length = 7;
   four->is_dwz = 1;
 
-  std::vector<std::unique_ptr<dwarf2_per_cu_data>> units;
+  std::vector<dwarf2_per_cu_data_up> units;
   units.push_back (std::move (one));
   units.push_back (std::move (two));
   units.push_back (std::move (three));
index 80f0e3ee13bb666bb7ea0e5f0afa8c5a6b0ad13f..756d1934ca0c2fced81d88b91090a7614159f90f 100644 (file)
@@ -74,6 +74,20 @@ struct dwarf2_queue_item
   enum language pretend_language;
 };
 
+/* A deleter for dwarf2_per_cu_data that knows to downcast to
+   signatured_type as appropriate.  This approach lets us avoid a
+   virtual destructor, which saves a bit of space.  */
+
+struct dwarf2_per_cu_data_deleter
+{
+  void operator() (dwarf2_per_cu_data *data);
+};
+
+/* A specialization of unique_ptr for dwarf2_per_cu_data and
+   subclasses.  */
+typedef std::unique_ptr<dwarf2_per_cu_data, dwarf2_per_cu_data_deleter>
+    dwarf2_per_cu_data_up;
+
 /* Some DWARF data can be shared across objfiles who share the same BFD,
    this data is stored in this object.
 
@@ -103,7 +117,7 @@ struct dwarf2_per_bfd
   /* A convenience function to allocate a dwarf2_per_cu_data.  The
      returned object has its "index" field set properly.  The object
      is allocated on the dwarf2_per_bfd obstack.  */
-  std::unique_ptr<dwarf2_per_cu_data> allocate_per_cu ();
+  dwarf2_per_cu_data_up allocate_per_cu ();
 
   /* A convenience function to allocate a signatured_type.  The
      returned object has its "index" field set properly.  The object
@@ -154,7 +168,7 @@ public:
 
   /* Table of all the compilation units.  This is used to locate
      the target compilation unit of a particular reference.  */
-  std::vector<std::unique_ptr<dwarf2_per_cu_data>> all_comp_units;
+  std::vector<dwarf2_per_cu_data_up> all_comp_units;
 
   /* Table of struct type_unit_group objects.
      The hash key is the DW_AT_stmt_list value.  */