Bug 29343 - [gdb/symtab] c++-ify comp_unit_head
Summary: [gdb/symtab] c++-ify comp_unit_head
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: symtab (show other bugs)
Version: HEAD
: P2 enhancement
Target Milestone: 14.1
Assignee: Tom Tromey
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-07-09 08:24 UTC by Tom de Vries
Modified: 2022-12-30 12:55 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
tentative patch (1.22 KB, patch)
2022-07-09 09:17 UTC, Tom de Vries
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Tom de Vries 2022-07-09 08:24:33 UTC
I ran into a race condition for per_cu->length, and while investigating this I noticed this particular requirement about length:
...
  /* The start offset and length of this compilation unit.                            
     NOTE: Unlike comp_unit_head.length, this length includes                         
     initial_length_size.                                                             
     If the DIE refers to a DWO file, this is always of the original die,             
     not the DWO file.  */
  sect_offset sect_off {};
  unsigned int length = 0;
...

Grepping through the sources shows 3 spots were this requirement is not met:
...
$ grep "cu->length = " gdb/dwarf2/read.c
  the_cu->length = length;
          this_cu->length = cu->header.get_length ();
            this_cu->length = cu->header.get_length ();
  this_cu->length = m_new_cu->header.get_length ();
      this_cu->length = cu_header.length + cu_header.initial_length_size;
...
Comment 1 Tom de Vries 2022-07-09 08:34:25 UTC
Oh, my mistake, in those cases we use get_length():
...
  unsigned int get_length () const
  {
    return initial_length_size + length;
  }
...
and in the other length:
...
      this_cu->length = cu_header.length + cu_header.initial_length_size;
...
Comment 2 Tom de Vries 2022-07-09 09:17:09 UTC
Created attachment 14200 [details]
tentative patch

This patch fixes the one use:
...
-      this_cu->length = cu_header.length + cu_header.initial_length_size;
+      this_cu->length = cu_header.get_length ();
...
and then proceeds to make the length field private, to enforce using the accessor.

That works reasonably well, but runs into trouble with this memset:
...
@@ -23377,8 +23377,6 @@ dwarf2_per_cu_data::get_header () const
       const gdb_byte *info_ptr
        = this->section->buffer + to_underlying (this->sect_off);
 
-      memset (&m_header, 0, sizeof (m_header));
-
       read_comp_unit_head (&m_header, info_ptr, this->section,
                           rcuh_kind::COMPILE);
 
...
which I removed in the patch, but I'm not sure yet that correct.
Comment 3 Tom de Vries 2022-07-11 09:40:26 UTC
(In reply to Tom de Vries from comment #2)
> Created attachment 14200 [details]
> tentative patch
> 
> This patch fixes the one use:
> ...
> -      this_cu->length = cu_header.length + cu_header.initial_length_size;
> +      this_cu->length = cu_header.get_length ();
> ...

I've committed this bit: https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=a4ca6efe0589d0a030920a4686b692208c82a028
Comment 4 Tom de Vries 2022-07-13 07:41:17 UTC
(In reply to Tom de Vries from comment #2)
> ...
> @@ -23377,8 +23377,6 @@ dwarf2_per_cu_data::get_header () const
>        const gdb_byte *info_ptr
>         = this->section->buffer + to_underlying (this->sect_off);
>  
> -      memset (&m_header, 0, sizeof (m_header));
> -
>        read_comp_unit_head (&m_header, info_ptr, this->section,
>                            rcuh_kind::COMPILE);
>  
> ...

Hmm, so struct comp_unit_head is a POD, that we init using memset, sometimes.

Sometimes we just initialize a bit, like this:
...
      /* Initialize it due to a false compiler warning.  */
      header.signature = -1;
      header.type_cu_offset_in_tu = (cu_offset) -1;
...

And sometime not at all (before the reading is done).

To make sure things are initialized consistently, we'd have to start using constructors, which I suppose means we no longer can use the memset.

So I guess this requires a larger rewrite.
Comment 5 Tom de Vries 2022-07-13 07:42:37 UTC
Update summary.
Comment 7 Tom de Vries 2022-12-25 08:25:26 UTC
(In reply to Tom de Vries from comment #2)
> and then proceeds to make the length field private, to enforce using the
> accessor.

This bit submitted here: https://sourceware.org/pipermail/gdb-patches/2022-December/195095.html
Comment 8 Sourceware Commits 2022-12-26 20:59:23 UTC
The master branch has been updated by Tom Tromey <tromey@sourceware.org>:

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

commit 4d78ce772370fa48b9a749f81205076f26eba846
Author: Tom Tromey <tom@tromey.com>
Date:   Fri Jul 15 19:05:29 2022 -0600

    Add initializers to comp_unit_head
    
    PR symtab/29343 points out that it would be beneficial if
    comp_unit_head had a constructor and used initializers.  This patch
    implements this.  I'm unsure if this is sufficient to close the bug,
    but at least it's a step.
    
    Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29343
Comment 9 Tom Tromey 2022-12-26 21:03:29 UTC
Fixed.
Comment 10 Sourceware Commits 2022-12-30 12:55:27 UTC
The master branch has been updated by Tom de Vries <vries@sourceware.org>:

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

commit d8f52a9a9ccbf7411cf4ae487d2756826f5d0bd5
Author: Tom de Vries <tdevries@suse.de>
Date:   Fri Dec 30 13:55:22 2022 +0100

    [gdb/symtab] Make comp_unit_head.length private
    
    Make comp_unit_head.length private, to enforce using accessor functions.
    
    Replace accessor function get_length with get_length_with_initial and
    get_length_without_initial, to make it explicit which variant we're using.
    
    Tested on x86_64-linux.
    
    PR symtab/29343
    Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29343