Bug 24480 - gdb drops toplevel types with -fdebug-types-section
Summary: gdb drops toplevel types with -fdebug-types-section
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: gdb (show other bugs)
Version: HEAD
: P2 normal
Target Milestone: 10.1
Assignee: Not yet assigned to anyone
URL:
Keywords:
: 25886 (view as bug list)
Depends on:
Blocks:
 
Reported: 2019-04-23 20:03 UTC by Tom de Vries
Modified: 2020-04-30 07:03 UTC (History)
4 users (show)

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


Attachments
Fix for missing top level types with -fdebug-types-section (348 bytes, patch)
2020-01-16 05:24 UTC, Mark
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Tom de Vries 2019-04-23 20:03:22 UTC
[ This might be a duplicate of PR14148. ]

Building trunk dwz with trunk gcc and CFLAGS="-O0 -ggdb3", I get with trunk gdb:
...
$ gdb -batch -ex "break dwz" -ex run -ex finish -ex "ptype res" -ex "ptype struct file_result" --args ./build/dwz
Breakpoint 1 at 0x415e40: file /data/dwz/build/../src/dwz.c, line 10982.

Breakpoint 1, dwz (file=0x41e94c "a.out", outfile=0x0, res=0x7fffffffdb10, resa=0x0, files=0x0) at /data/dwz/build/../src/dwz.c:10982
10982     res->res = -1;
/data/dwz/build/dwz: Failed to open input file a.out: No such file or directory
0x0000000000401e6a in main (argc=1, argv=0x7fffffffdc48) at /data/dwz/build/../src/dwz.c:11922
11922         ret = dwz (optind == argc ? "a.out" : argv[optind], outfile,
Value returned is $1 = 1
type = struct file_result {
    int res;
    dev_t dev;
    ino_t ino;
    nlink_t nlink;
}
type = struct file_result {
    int res;
    dev_t dev;
    ino_t ino;
    nlink_t nlink;
}
...

and with CFLAGS="-O0 -ggdb3 -fdebug-types-section" instead I get:
...
$ ~/gdb_versions/devel/gdb -batch -ex "break dwz" -ex run -ex finish -ex "ptype res" -ex "ptype struct file_result" --args ./build/dwz
Breakpoint 1 at 0x415e40: file /data/dwz/build/../src/dwz.c, line 10982.

Breakpoint 1, dwz (file=0x41e94c "a.out", outfile=0x0, res=0x7fffffffdb10, resa=0x0, files=0x0) at /data/dwz/build/../src/dwz.c:10982
10982     res->res = -1;
/data/dwz/build/dwz: Failed to open input file a.out: No such file or directory
0x0000000000401e6a in main (argc=1, argv=0x7fffffffdc48) at /data/dwz/build/../src/dwz.c:11922
11922         ret = dwz (optind == argc ? "a.out" : argv[optind], outfile,
Value returned is $1 = 1
type = struct file_result {
    int res;
    dev_t dev;
    ino_t ino;
    nlink_t nlink;
}
No struct type named file_result.
...


So there's:
...
  Compilation Unit @ offset 0x0:
   Length:        0xb7 (32-bit)
   Version:       4
   Abbrev Offset: 0x64
   Pointer Size:  8
   Signature:     0x314134da8877517a
   Type Offset:   0x1d
 <0><17>: Abbrev Number: 1 (DW_TAG_type_unit)
    <18>   DW_AT_language    : 12       (ANSI C99)
    <19>   DW_AT_stmt_list   : 0xe9
 <1><1d>: Abbrev Number: 2 (DW_TAG_structure_type)
    <1e>   DW_AT_name        : (indirect string, offset: 0x13163): file_result
...
and:
...
 <1><e4b7>: Abbrev Number: 51 (DW_TAG_structure_type)
    <e4b8>   DW_AT_signature   : signature: 0x314134da8877517a
...
which is the type of res:
...
 <2><c65>: Abbrev Number: 64 (DW_TAG_variable)
    <c66>   DW_AT_name        : res
    <c6a>   DW_AT_decl_file   : 1
    <c6b>   DW_AT_decl_line   : 11845
    <c6d>   DW_AT_decl_column : 22
    <c6e>   DW_AT_type        : <0xe4b7>
    <c72>   DW_AT_location    : 3 byte block: 91 e0 7d  (DW_OP_fbreg: -288)
...
but struct file_result as a toplevel type goes missing.
Comment 1 Tom de Vries 2019-04-24 19:08:52 UTC
The problem is that this die: 
...
 <1><123d>: Abbrev Number: 67 (DW_TAG_structure_type)
    <123e>   DW_AT_name        : (indirect string, offset: 0x4980): file_result
    <1242>   DW_AT_signature   : signature: 0x314134da8877517a
    <124a>   DW_AT_declaration : 1
...
is skipped here in process_structure_scope:
...
  /* Do not consider external references.  According to the DWARF standard,                                       
     these DIEs are identified by the fact that they have no byte_size                                            
     attribute, and a declaration attribute.  */
  if (dwarf2_attr (die, DW_AT_byte_size, cu) != NULL
      || !die_is_declaration (die, cu))
    {
...

The comment references the DWARF standard (v4, 5.5.1 Structure, Union and Class Type Entries):
...
An incomplete structure, union or class type is represented by a structure, union or class entry that does not have a byte size attribute and that has a DW_AT_declaration attribute.
...

But the code does not handle the following bit:
...
If the complete declaration of a type has been placed in a separate type unit (see Section 3.1.3), an incomplete declaration of that type in the compilation unit may provide the unique 64-bit signature of the type using a DW_AT_signature attribute.
...

Using this tentative patch:
...
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index e1829358aa..7f82ce5a33 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -20101,7 +20101,8 @@ die_is_declaration (struct die_info *die, struct dwarf2_cu *cu)
      to a different DIE referenced by the specification attribute,
      even though the given DIE does not have a declaration attribute.  */
   return (dwarf2_flag_true_p (die, DW_AT_declaration, cu)
-         && dwarf2_attr (die, DW_AT_specification, cu) == NULL);
+         && dwarf2_attr (die, DW_AT_specification, cu) == NULL
+         && dwarf2_attr (die, DW_AT_signature, cu) == NULL);
 }
 
 /* Return the die giving the specification for DIE, if there is
...
I get the expected:
...
$ ./gdb -batch -ex "break dwz" -ex run -ex finish -ex "ptype res" -ex "ptype struct file_result" --args ./build/dwz
Breakpoint 1 at 0x425d9a: file /data/dwz/build/../src/dwz.c, line 10984.

Breakpoint 1, dwz (file=0x431d31 "a.out", outfile=0x0, res=0x7fffffffda70, resa=0x0, files=0x0) at /data/dwz/build/../src/dwz.c:10984
10984     int ret = 0, fd;
/data/dwz/build/dwz: Failed to open input file a.out: No such file or directory
0x000000000042887a in main (argc=1, argv=0x7fffffffdc68) at /data/dwz/build/../src/dwz.c:11928
11928         ret = dwz (optind == argc ? "a.out" : argv[optind], outfile,
Value returned is $1 = 1
type = struct file_result {
    int res;
    dev_t dev;
    ino_t ino;
    nlink_t nlink;
}
type = struct file_result {
    int res;
    dev_t dev;
    ino_t ino;
    nlink_t nlink;
}
...
Comment 2 Tom de Vries 2019-04-26 08:37:55 UTC
Regression due to " Set list_in_scope later in DWARF reader":
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=93b8bea4143cafae79076076c64aaa4c46a9b73c
Comment 3 Tom de Vries 2019-04-26 11:07:29 UTC
Minimal test-case dwz.c:
...
struct foo
{
  int i;
};
struct foo var1;

struct file_result
{
  int res;
};
struct file_result var2;

int
main (void)
{
  struct file_result res;
  return 0;
}
...

compiled like this (either vanilla gcc trunk, or gcc 7.4.0 on openSUSE leap 15.0):
...
$ gcc -O0 -ggdb3 -fdebug-types-section src/dwz.c -o build/dwz
...

With gdb.ok (gdb-8.2.1), and gdb.bad (master), we get:
...
$ for gdb in ./gdb.ok ./gdb.bad ; do \
    echo $gdb; \
    $gdb \
      -readnow \
      -batch \
      -ex "break main" \
      -ex run \
      -ex "ptype struct file_result" \
      -ex "ptype struct foo" --args build/dwz \
      2>&1 | egrep "file_result|foo"; \
  done
./gdb.ok
struct file_result {
struct foo {
./gdb.bad
No struct type named file_result.
type = struct foo {
...
Comment 4 Mark 2020-01-16 05:24:21 UTC
Created attachment 12214 [details]
Fix for missing top level types with -fdebug-types-section

This fixes the issue.

The problem is it relies on start_symtab to set list_in_scope, but start_symtab is only called for the first tu that contributes to a symtab. Since each type is in its own tu, only one type goes into the file scope table. Just set it on the other paths too.
Comment 5 Christian Biesinger 2020-01-16 19:46:23 UTC
Mark, could you send that patch to the gdb-patches@sourceware.org mailing list, as per https://sourceware.org/gdb/wiki/ContributionChecklist ?
Comment 6 Tom de Vries 2020-04-28 11:45:38 UTC
(In reply to Christian Biesinger from comment #5)
> Mark, could you send that patch to the gdb-patches@sourceware.org mailing
> list, as per https://sourceware.org/gdb/wiki/ContributionChecklist ?

https://sourceware.org/pipermail/gdb-patches/2020-January/164813.html
Comment 7 Sourceware Commits 2020-04-28 14:12:49 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=770479f223ecd1920dd3cc683b05b24af25c4613

commit 770479f223ecd1920dd3cc683b05b24af25c4613
Author: Mark Williams <mark@myosotissp.com>
Date:   Tue Apr 28 16:12:45 2020 +0200

    gdb: Fix toplevel types with -fdebug-types-section
    
    When debugging a program compiled with -fdebug-types-section,
    only the first top-level type in each file is visible to gdb.
    
    The problem was caused by moving the assignment to list_in_scope
    from process_full_comp_unit and process_full_type_unit to
    start_symtab.  This was fine for process_full_comp_unit, because
    symtabs and comp units are one-to-one.  But there can be many type
    units per symtab (one for each type), and we only call start_symtab
    for the first one.  This adds the necessary assignments on the paths
    where start_symtab is not called.
    
    gdb/Changelog:
    
    2020-04-28 Mark Williams <mark@myosotissp.com>
    
            PR gdb/24480
            * dwarf2read.c: Add missing assingments to list_in_scope when
            start_symtab was already called.
    
    gdb/testsuite/Changelog:
    
    2020-04-28 Mark Williams <mark@myosotissp.com>
    
            PR gdb/24480
            * dw4-toplevel-types.exp: Test for top level types.
            * dw4-toplevel-types.cc: Test for top level types.
Comment 8 Tom de Vries 2020-04-28 14:44:45 UTC
*** Bug 25886 has been marked as a duplicate of this bug. ***
Comment 9 Tom de Vries 2020-04-28 14:50:22 UTC
I've retested the minimal test-case from comment 3, and can confirm it passes with the committed patch.

Patch with test-case committed, marking resolved-fixed.
Comment 10 Tom de Vries 2020-04-30 07:03:26 UTC
FTR, the same problem was found, and a similar patch proposed here ( https://sourceware.org/pipermail/gdb/2020-March/000016.html ).