Bug 25718 - [ada] symbol in imported unit not found
Summary: [ada] symbol in imported unit not found
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: symtab (show other bugs)
Version: HEAD
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-03-24 14:14 UTC by Tom de Vries
Modified: 2020-04-14 13:33 UTC (History)
0 users

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


Attachments
a.out (4.50 KB, application/x-executable)
2020-03-28 17:04 UTC, Tom de Vries
Details
b.out (4.50 KB, application/x-executable)
2020-03-28 17:05 UTC, Tom de Vries
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Tom de Vries 2020-03-24 14:14:50 UTC
Consider test-case gdb.ada/char_enum.exp run on target board unix/-flto/-O0/-flto-partition=none/-ffat-lto-objects.

Printing type pck.Global_Enum_Type works fine:
...
$ gdb outputs/gdb.ada/char_enum/foo -batch -iex "set language ada" -ex "b foo.adb:23" -ex r -ex "ptype pck.Global_Enum_Type"
Breakpoint 1 at 0x402c62: file foo.adb, line 23.

Breakpoint 1, foo () at foo.adb:23
23         Do_Nothing (Char'Address);  -- STOP
type = ('x', 'Y', '+')
...

And using maint print psymbols, we find that there are two partial symtabs that contain the symbol, here:
...
Partial symtab for source file foo.adb (object 0x3363850)

  Read from object file outputs/gdb.ada/char_enum/foo (0x2bf4b10)
  Full symtab was read (at 0x33878b0)
  Symbols cover text addresses 0x0-0x0
  Address map supported - yes.
  Depends on 0 other partial symtabs.
  Static partial symbols:
    `pck__Qx'  `<pck__Qx>', constant int, 0x0
    `pck__QU59'  `<pck__QU59>', constant int, 0x0
    `pck__QU2b'  `<pck__QU2b>', constant int, 0x0
    `system__address'  `system.address', type, 0x0
    `integer'  `integer', type, 0x0
    `integer_8'  `integer_8', type, 0x0
    `pck__global_enum_type'  `pck.global_enum_type', struct domain, type, 0x0
...
and here:
...
Partial symtab for source file foo.adb (object 0x33636d0)

  Read from object file outputs/gdb.ada/char_enum/foo (0x2bf4b10)
  Symbols cover text addresses 0x0-0x0
  Address map supported - yes.
  Depends on 0 other partial symtabs.
  Shared partial symtab with user 0x336c990
  Static partial symbols:
    `pck__Qx'  `<pck__Qx>', constant int, 0x0
    `pck__QU59'  `<pck__QU59>', constant int, 0x0
    `pck__QU2b'  `<pck__QU2b>', constant int, 0x0
    `system__address'  `system.address', type, 0x0
    `integer'  `integer', type, 0x0
    `integer_8'  `integer_8', type, 0x0
    `pck__global_enum_type'  `pck.global_enum_type', struct domain, type, 0x0
...

The fact that there are two symtabs is due to PR25700 - "Forward-imported CU causes duplicate partial symtab".

However, adding a bit of debugging in psym_map_matching_symbols:
...
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 2822d40c8c..56283e50b1 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -5452,6 +5452,7 @@ aux_add_nonlocal_symbols (struct block_symbol *bsym,
        data->arg_sym = sym;
       else
        {
+         fprintf (stderr, "Found sym in aux_add_nonlocal_symbols: %s\n", bsym->symbol->m_name);
          data->found_sym = 1;
          add_defn_to_vec (data->obstackp,
                           fixup_symbol_section (sym, data->objfile),
diff --git a/gdb/psymtab.c b/gdb/psymtab.c
index 8aa9c6e87b..053c309e95 100644
--- a/gdb/psymtab.c
+++ b/gdb/psymtab.c
@@ -1181,9 +1181,24 @@ psym_map_matching_symbols
   for (partial_symtab *ps : require_partial_symbols (objfile, true))
     {
       QUIT;
-      if (ps->readin_p ()
-         || match_partial_symbol (objfile, ps, global, name, domain,
-                                  ordered_compare))
+      bool do_search = false;
+      
+      if (ps->readin_p ())
+       {
+         fprintf (stderr, "psymtab already expanded, going to do search\n");
+         do_search = true;
+       }
+      else if (match_partial_symbol (objfile, ps, global, name, domain,
+                                    ordered_compare))
+       {
+         fprintf (stderr, "Found partial symbol in psym_map_matching_symbols: %s, going to expand and do sear
ch\n",
+                  name.name().c_str());
+         do_search = true;
+       }
+      else
+       fprintf (stderr, "psymtab not expanded and partial symbol not found, not doing search\n");
+
+      if (do_search)
        {
          struct compunit_symtab *cust = psymtab_to_symtab (objfile, ps);
          const struct block *block;
...
we find:
...
psymtab not expanded and partial symbol not found, not doing search
psymtab already expanded, going to do search
Found sym in aux_add_nonlocal_symbols: pck__global_enum_type
psymtab already expanded, going to do search
psymtab already expanded, going to do search
psymtab not expanded and partial symbol not found, not doing search
Found partial symbol in psym_map_matching_symbols: pck__global_enum_type, going to expand and do search
psymtab not expanded and partial symbol not found, not doing search
...

So, first we find the symbol in an already expanded symtab:
...
psymtab already expanded, going to do search
Found sym in aux_add_nonlocal_symbols: pck__global_enum_type
...

Then we find the symbol in a partial symtab. We then expand it, but ... do not find the symbol in the expanded symtab:
...
psymtab not expanded and partial symbol not found, not doing search
Found partial symbol in psym_map_matching_symbols: pck__global_enum_type, going to expand and do search
psymtab not expanded and partial symbol not found, not doing search
...

We should be finding two symbols here, not one.

And AFAIU, that is the root cause for the regression with the tentative fix for PR25700: once we remove the duplicate symtab, we find no symbol, instead of one.
Comment 1 Tom de Vries 2020-03-24 16:33:25 UTC
Another way to see the same issue using the exec from gdb.dwarf2/imported-unit.exp:
...
$ gdb -batch outputs/gdb.dwarf2/imported-unit/imported-unit -ex "maint expand-symtabs" -ex "maint info psymtabs"
...

We have:
...
  { psymtab imported_unit.c ((struct partial_symtab *) 0x2ab06d0)
    readin yes
    fullname (null)
    text addresses 0x0 -- 0x0
    psymtabs_addrmap_supported yes
    globals (none)
    statics (* (struct partial_symbol **) 0x2a62310 @ 1)
    dependencies (none)
  }
...
and:
...
  { psymtab imported_unit.c ((struct partial_symtab *) 0x2a7f8b0)
    readin no
    fullname (null)
    text addresses 0x0 -- 0x0
    psymtabs_addrmap_supported yes
    globals (none)
    statics (* (struct partial_symbol **) 0x2a62308 @ 1)
    user <artificial>@0xc7 ((struct partial_symtab *) 0x2ab1c30)
    dependencies (none)
  }
...

The expansion for the second unit has failed (readin no).
Comment 2 Tom de Vries 2020-03-28 16:58:34 UTC
Patch submitted at https://sourceware.org/pipermail/gdb-patches/2020-March/167076.html
Comment 3 Tom de Vries 2020-03-28 17:04:20 UTC
Created attachment 12411 [details]
a.out

Executable belonging to test-case described in submitted patch:
...
$ gcc -g hello.c -o a.out
...
Comment 4 Tom de Vries 2020-03-28 17:05:26 UTC
Created attachment 12413 [details]
b.out

Dwz-ed executable belonging to test-case described in submitted patch:
...
$ dwz a.out -o b.out
...
Comment 5 Sourceware Commits 2020-04-14 13:30:55 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=194d088fb1fa6c3c341994ca247d172c3f08c2da

commit 194d088fb1fa6c3c341994ca247d172c3f08c2da
Author: Tom de Vries <tdevries@suse.de>
Date:   Tue Apr 14 15:30:50 2020 +0200

    [gdb] Fix missing symtab includes
    
    [ The test-case requires commit c1a66c0629 "[gdb] Expand symbolless symtabs
    using maint expand-symtabs". ]
    
    Consider the debug info for the test-case included in this patch.  It consists
    of a PU:
    ...
     <0><d2>: Abbrev Number: 2 (DW_TAG_partial_unit)
     <1><d3>: Abbrev Number: 0
    ...
    imported by a CU:
    ...
     <0><df>: Abbrev Number: 2 (DW_TAG_compile_unit)
        <e0>   DW_AT_language    : 2        (non-ANSI C)
        <e1>   DW_AT_stmt_list   : 0xe9
     <1><e5>: Abbrev Number: 3 (DW_TAG_imported_unit)
        <e6>   DW_AT_import      : <0xd2>   [Abbrev Number: 2]
     <1><ea>: Abbrev Number: 0
    ...
    and the CU has a dw2-symtab-includes.h file in the .debug_line file name
    table:
    ...
     The Directory Table (offset 0x101):
      1     /data/gdb_versions/devel/src/gdb/testsuite/gdb.dwarf2
    
     The File Name Table (offset 0x138):
      Entry Dir     Time    Size    Name
      1     1       0       0       dw2-symtab-includes.h
    ...
    
    After expanding all symtabs, we can see the CU listed in the user field of the
    PU, and vice-versa the PU listed in the includes of the CU:
    ...
    $ gdb.sh -batch \
      -iex "set language c" \
      outputs/gdb.dwarf2/dw2-symtab-includes/dw2-symtab-includes \
      -ex "maint expand-symtabs" \
      -ex "maint info symtabs"
      ...
      { ((struct compunit_symtab *) 0x394dd60)
        debugformat DWARF 2
        producer (null)
        dirname (null)
        blockvector ((struct blockvector *) 0x394dea0)
        user ((struct compunit_symtab *) 0x394dba0)
      }
      { ((struct compunit_symtab *) 0x394dba0)
        debugformat DWARF 2
        producer (null)
        dirname (null)
        blockvector ((struct blockvector *) 0x394dd10)
        user ((struct compunit_symtab *) (null))
        ( includes
          ((struct compunit_symtab *) 0x394dd60)
        )
      }
    ...
    
    But if we instead only expand the symtab for the dw2-symtab-includes.h file,
    the includes and user links are gone:
    ...
    $ gdb -batch \
      -iex "set language c" \
      outputs/gdb.dwarf2/dw2-symtab-includes/dw2-symtab-includes \
      -ex "maint expand-symtabs dw2-symtab-includes.h" \
      -ex "maint info symtabs"
      ...
      { ((struct compunit_symtab *) 0x2728210)
        debugformat DWARF 2
        producer (null)
        dirname (null)
        blockvector ((struct blockvector *) 0x2728350)
        user ((struct compunit_symtab *) (null))
      }
      { ((struct compunit_symtab *) 0x2728050)
        debugformat DWARF 2
        producer (null)
        dirname (null)
        blockvector ((struct blockvector *) 0x27281c0)
        user ((struct compunit_symtab *) (null))
      }
    ...
    
    The includes are calculated by process_cu_includes in gdb/dwarf2/read.c.
    
    In the case of expanding all symtabs:
    - the CU partial symtab is expanded using psymtab_to_symtab
    - psymtab_to_symtab calls dwarf2_psymtab::read_symtab
    - dwarf2_psymtab::read_symtab calls dwarf2_psymtab::expand_psymtab
    - dwarf2_psymtab::read_symtab calls process_cu_includes, and we have the
      includes
    
    In the case of expanding the symtab for dw2-symtab-includes.h:
    - the dw2-symtab-includes.h partial symtab is expanded using psymtab_to_symtab
    - psymtab_to_symtab calls dwarf2_include_psymtab::read_symtab
    - dwarf2_include_psymtab::read_symtab calls
      dwarf2_include_psymtab::expand_psymtab
    - dwarf2_include_psymtab::expand_psymtab calls
      partial_symtab::expand_dependencies
    - partial_symtab::expand_dependencies calls dwarf2_psymtab::expand_psymtab
      for the CU partial symtab
    - the CU partial symtab is expanded using dwarf2_psymtab::expand_psymtab
    - process_cu_includes is never called
    
    Fix this by making sure in dwarf2_include_psymtab::read_symtab that
    read_symtab is called for the CU partial symtab.
    
    Tested on x86_64-linux, with native, and target board cc-with-dwz and
    cc-with-dwz-m.
    
    In addition, tested test-case with target boards cc-with-gdb-index.exp,
    cc-with-debug-names.exp and readnow.exp.
    
    gdb/ChangeLog:
    
    2020-04-14  Simon Marchi  <simon.marchi@polymtl.ca>
                Tom de Vries  <tdevries@suse.de>
    
            PR symtab/25718
            * psympriv.h (struct partial_symtab::read_symtab)
            (struct partial_symtab::expand_psymtab)
            (struct partial_symtab::read_dependencies): Update comments.
            * dwarf2/read.c (struct dwarf2_include_psymtab::read_symtab): Call
            read_symtab for includer.
            (struct dwarf2_include_psymtab::expand_psymtab): Assert false.
            (struct dwarf2_include_psymtab::readin_p): Call readin_p () for includer.
            (struct dwarf2_include_psymtab::m_readin): Remove.
            (struct dwarf2_include_psymtab::includer): New member function.
            (dwarf2_psymtab::expand_psymtab): Assert !readin.
    
    gdb/testsuite/ChangeLog:
    
    2020-04-14  Tom de Vries  <tdevries@suse.de>
    
            PR symtab/25718
            * gdb.dwarf2/dw2-symtab-includes.exp: New file.
Comment 6 Tom de Vries 2020-04-14 13:33:58 UTC
Patch with test-case committed, marking resolved-fixed.