Bug 32158 - [gdb/symtab] enum class enumerator has incorrect parent in cooked index
Summary: [gdb/symtab] enum class enumerator has incorrect parent in cooked index
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: symtab (show other bugs)
Version: HEAD
: P2 normal
Target Milestone: 15.2
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks: 29366
  Show dependency treegraph
 
Reported: 2024-09-10 12:00 UTC by Tom de Vries
Modified: 2024-09-15 15:11 UTC (History)
2 users (show)

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


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Tom de Vries 2024-09-10 12:00:35 UTC
Consider test-case:
...
$ cat test.c
namespace ns
{
  enum class e
  {
    val1 = 0x1,
  };
}

int
main (void)
{
  return (int)ns::e::val1;
}
$ g++ test.c -g
$ ./a.out ; echo $?
1
...

With:
...
$ gdb -q -batch a.out -ex "maint print objfile"
...
we get:
...
    [7] ((cooked_index_entry *) 0x7f3be8002ef0)
    name:       val1
    canonical:  val1
    qualified:  ns::val1
    DWARF tag:  DW_TAG_enumerator
    flags:      0x0 []
    DIE offset: 0xe8
    parent:     ((cooked_index_entry *) 0x7f3be8002e90) [ns]
...

The parent is wrong, it should be e instead of ns and consequently the qualified name is incorrect, it should be ns::e::val1 instead of ns::val1.

Like PR31900, this is a regression since commit e976ec82834 "Change handling of DW_TAG_enumeration_type in DWARF scanner".  With that patch reverted, we have instead:
...
    [7] ((cooked_index_entry *) 0x7f21a4003fa0)
    name:       val1
    canonical:  val1
    qualified:  ns::e::val1
    DWARF tag:  DW_TAG_enumerator
    flags:      0x0 []
    DIE offset: 0xe8
    parent:     ((cooked_index_entry *) 0x7f21a4003f70) [e]
...

AFAIU, the problem with that patch is that it looks for the DW_AT_enum_class attribute in the DW_TAG_enumerator DIE instead of in the DW_TAG_enumeration_type DIE, and consequently treats any enum class as an enum.
Comment 1 Tom de Vries 2024-09-12 11:56:23 UTC
Proposed fix: revert the commit: https://sourceware.org/pipermail/gdb-patches/2024-September/211683.html
Comment 2 Sourceware Commits 2024-09-14 12:10:02 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=93a20d956e633cc1a87e68d88d2fc51adc787857

commit 93a20d956e633cc1a87e68d88d2fc51adc787857
Author: Tom de Vries <tdevries@suse.de>
Date:   Sat Sep 14 14:09:35 2024 +0200

    [gdb/testsuite] Add regression test for PR32158
    
    Consider test-case:
    ...
    namespace ns {
      enum class ec {
        val2 = 2
      };
    }
    
    int main () {
      return (int)ns::ec::val2;
    }
    ...
    compiled with debug info:
    ...
    $ g++ test.c -g
    ...
    
    When looking at the cooked index entry for val2 using "maint print objfiles",
    we get:
    ...
        [7] ((cooked_index_entry *) 0x7f8ecc002ef0)
        name:       val2
        canonical:  val2
        qualified:  ns::val2
        DWARF tag:  DW_TAG_enumerator
        flags:      0x0 []
        DIE offset: 0xe9
        parent:     ((cooked_index_entry *) 0x7f8ecc002e90) [ns]
    ...
    which is wrong, there is no source level entity ns::val2.
    
    This is PR symtab/32158.
    
    This is a regression since commit 4e417d7bb1c ("Change handling of
    DW_TAG_enumeration_type in DWARF scanner").
    
    Reverting the commit on current trunk fixes the problem, and gets us instead:
    ...
        [7] ((cooked_index_entry *) 0x7fba70002ef0)
        name:       val2
        canonical:  val2
        qualified:  ns::ec::val2
        DWARF tag:  DW_TAG_enumerator
        flags:      0x0 []
        DIE offset: 0xe9
        parent:     ((cooked_index_entry *) 0x7fba70002ec0) [ec]
    ...
    
    Add a regression test for this PR in test-case gdb.dwarf2/enum-type-c++.exp.
    
    Tested on x86_64-linux.
    
    Approved-By: Tom Tromey <tom@tromey.com>
    
    Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32158
Comment 3 Sourceware Commits 2024-09-14 12:10:07 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=a2860473ef13cfebcd9fddc067b7b36ca56c6b81

commit a2860473ef13cfebcd9fddc067b7b36ca56c6b81
Author: Tom de Vries <tdevries@suse.de>
Date:   Sat Sep 14 14:09:35 2024 +0200

    [gdb/symtab] Revert "Change handling of DW_TAG_enumeration_type in DWARF scanner"
    
    After adding dwarf assembly to test-case gdb.dwarf2/enum-type.exp that adds
    this debug info:
    ...
     <1><11f>: Abbrev Number: 3 (DW_TAG_enumeration_type)
        <120>   DW_AT_specification: <0x130>
     <2><124>: Abbrev Number: 4 (DW_TAG_enumerator)
        <125>   DW_AT_name        : val1
        <12a>   DW_AT_const_value : 1
     <2><12b>: Abbrev Number: 0
     <1><12c>: Abbrev Number: 5 (DW_TAG_namespace)
        <12d>   DW_AT_name        : ns
     <2><130>: Abbrev Number: 6 (DW_TAG_enumeration_type)
        <131>   DW_AT_name        : e
        <133>   DW_AT_type        : <0x118>
        <137>   DW_AT_declaration : 1
    ...
    I run into an assertion failure:
    ...
    (gdb) file enum-type^M
    Reading symbols from enum-type...^M
    cooked-index.h:214: internal-error: get_parent: \
      Assertion `(flags & IS_PARENT_DEFERRED) == 0' failed.^M
    ...
    
    This was reported in PR32160 comment 1.
    
    This is a regression since commit 4e417d7bb1c ("Change handling of
    DW_TAG_enumeration_type in DWARF scanner").
    
    Fix this by reverting the commit.
    
    [ Also drop the kfails for PR31900 and PR32158, which are regressions by that
    same commit. ]
    
    That allows us to look at the output of "maint print objfiles", and for val1
    we get an entry without parent:
    ...
        [27] ((cooked_index_entry *) 0x7fbbb4002ef0)
        name:       val1
        canonical:  val1
        qualified:  val1
        DWARF tag:  DW_TAG_enumerator
        flags:      0x0 []
        DIE offset: 0x124
        parent:     ((cooked_index_entry *) 0)
    ...
    which is incorrect, as noted in that same comment, but an improvement over the
    assertion failure, and I don't think that ever worked.  This is to be
    addressed in a follow-up patch.
    
    Reverting the commit begs the question: what was it trying to fix in the first
    place, and do we need a different fix?  I've investigated this and filed
    PR32160 to track this.
    
    My guess is that the commit was based on a misunderstand of what we track
    in cooked_indexer::m_die_range_map.
    
    Each DIE has two types of parent DIEs:
    - a DIE that is the parent as indicated by the tree structure in which DIEs
      occur, and
    - a DIE that represent the parent scope.
    
    In most cases, these two are the same, but some times they're not.
    
    The debug info above demonstrates such a case.  The DIE at 0x11f:
    - has a tree-parent: the DIE representing the CU, and
    - has a scope-parent: DIE 0x12c representing namespace ns.
    
    In cooked_indexer::m_die_range_map, we track scope-parents, and the commit
    tried to add a tree-parent instead.
    
    So, I don't think we need a different fix, and propose we backport the reversal
    for gdb 15.2.
    
    Tested on x86_64-linux.
    
    Approved-By: Tom Tromey <tom@tromey.com>
    
    Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31900
    Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32158
    Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32160
Comment 4 Sourceware Commits 2024-09-15 13:31:14 UTC
The gdb-15-branch branch has been updated by Tom de Vries <vries@sourceware.org>:

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

commit 9ca807bc5f3ba68e736368b4e3bd942028cb566b
Author: Tom de Vries <tdevries@suse.de>
Date:   Sun Sep 15 15:30:53 2024 +0200

    [gdb/testsuite] Add regression test for PR32158
    
    Consider test-case:
    ...
    namespace ns {
      enum class ec {
        val2 = 2
      };
    }
    
    int main () {
      return (int)ns::ec::val2;
    }
    ...
    compiled with debug info:
    ...
    $ g++ test.c -g
    ...
    
    When looking at the cooked index entry for val2 using "maint print objfiles",
    we get:
    ...
        [7] ((cooked_index_entry *) 0x7f8ecc002ef0)
        name:       val2
        canonical:  val2
        qualified:  ns::val2
        DWARF tag:  DW_TAG_enumerator
        flags:      0x0 []
        DIE offset: 0xe9
        parent:     ((cooked_index_entry *) 0x7f8ecc002e90) [ns]
    ...
    which is wrong, there is no source level entity ns::val2.
    
    This is PR symtab/32158.
    
    This is a regression since commit 4e417d7bb1c ("Change handling of
    DW_TAG_enumeration_type in DWARF scanner").
    
    Reverting the commit on current trunk fixes the problem, and gets us instead:
    ...
        [7] ((cooked_index_entry *) 0x7fba70002ef0)
        name:       val2
        canonical:  val2
        qualified:  ns::ec::val2
        DWARF tag:  DW_TAG_enumerator
        flags:      0x0 []
        DIE offset: 0xe9
        parent:     ((cooked_index_entry *) 0x7fba70002ec0) [ec]
    ...
    
    Add a regression test for this PR in test-case gdb.dwarf2/enum-type-c++.exp.
    
    Tested on x86_64-linux.
    
    Approved-By: Tom Tromey <tom@tromey.com>
    
    Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32158
    (cherry picked from commit 93a20d956e633cc1a87e68d88d2fc51adc787857)
Comment 5 Sourceware Commits 2024-09-15 13:31:20 UTC
The gdb-15-branch branch has been updated by Tom de Vries <vries@sourceware.org>:

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

commit 21528df40e76ade452960d0325d86803e861ec3b
Author: Tom de Vries <tdevries@suse.de>
Date:   Sun Sep 15 15:30:53 2024 +0200

    [gdb/symtab] Revert "Change handling of DW_TAG_enumeration_type in DWARF scanner"
    
    After adding dwarf assembly to test-case gdb.dwarf2/enum-type.exp that adds
    this debug info:
    ...
     <1><11f>: Abbrev Number: 3 (DW_TAG_enumeration_type)
        <120>   DW_AT_specification: <0x130>
     <2><124>: Abbrev Number: 4 (DW_TAG_enumerator)
        <125>   DW_AT_name        : val1
        <12a>   DW_AT_const_value : 1
     <2><12b>: Abbrev Number: 0
     <1><12c>: Abbrev Number: 5 (DW_TAG_namespace)
        <12d>   DW_AT_name        : ns
     <2><130>: Abbrev Number: 6 (DW_TAG_enumeration_type)
        <131>   DW_AT_name        : e
        <133>   DW_AT_type        : <0x118>
        <137>   DW_AT_declaration : 1
    ...
    I run into an assertion failure:
    ...
    (gdb) file enum-type^M
    Reading symbols from enum-type...^M
    cooked-index.h:214: internal-error: get_parent: \
      Assertion `(flags & IS_PARENT_DEFERRED) == 0' failed.^M
    ...
    
    This was reported in PR32160 comment 1.
    
    This is a regression since commit 4e417d7bb1c ("Change handling of
    DW_TAG_enumeration_type in DWARF scanner").
    
    Fix this by reverting the commit.
    
    [ Also drop the kfails for PR31900 and PR32158, which are regressions by that
    same commit. ]
    
    That allows us to look at the output of "maint print objfiles", and for val1
    we get an entry without parent:
    ...
        [27] ((cooked_index_entry *) 0x7fbbb4002ef0)
        name:       val1
        canonical:  val1
        qualified:  val1
        DWARF tag:  DW_TAG_enumerator
        flags:      0x0 []
        DIE offset: 0x124
        parent:     ((cooked_index_entry *) 0)
    ...
    which is incorrect, as noted in that same comment, but an improvement over the
    assertion failure, and I don't think that ever worked.  This is to be
    addressed in a follow-up patch.
    
    Reverting the commit begs the question: what was it trying to fix in the first
    place, and do we need a different fix?  I've investigated this and filed
    PR32160 to track this.
    
    My guess is that the commit was based on a misunderstand of what we track
    in cooked_indexer::m_die_range_map.
    
    Each DIE has two types of parent DIEs:
    - a DIE that is the parent as indicated by the tree structure in which DIEs
      occur, and
    - a DIE that represent the parent scope.
    
    In most cases, these two are the same, but some times they're not.
    
    The debug info above demonstrates such a case.  The DIE at 0x11f:
    - has a tree-parent: the DIE representing the CU, and
    - has a scope-parent: DIE 0x12c representing namespace ns.
    
    In cooked_indexer::m_die_range_map, we track scope-parents, and the commit
    tried to add a tree-parent instead.
    
    So, I don't think we need a different fix, and propose we backport the reversal
    for gdb 15.2.
    
    Tested on x86_64-linux.
    
    Approved-By: Tom Tromey <tom@tromey.com>
    
    Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31900
    Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32158
    Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32160
    (cherry picked from commit a2860473ef13cfebcd9fddc067b7b36ca56c6b81)
Comment 6 Tom de Vries 2024-09-15 15:11:41 UTC
Fixed in trunk and gdb-15-branch.