Bug 28004 - DW_AT_ranges with form DW_FORM_sec_offset problem
Summary: DW_AT_ranges with form DW_FORM_sec_offset problem
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: symtab (show other bugs)
Version: HEAD
: P2 normal
Target Milestone: 11.1
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-06-22 05:26 UTC by Simon Marchi
Modified: 2021-08-06 16:05 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 Simon Marchi 2021-06-22 05:26:23 UTC
Using the repro files I will provide subsequently (it might be a bit large, I might have to host it externally), extracted to /tmp/repro, run this a first time:

$ ./gdb -nx --data-directory=data-directory -iex "set index-cache on" -iex "set sysroot /tmp/repro" /tmp/repro/gdb  /tmp/repro/core -ex bt -batch
...
warning: (Internal error: pc 0x7ff8feb2c21d in read in psymtab, but not in symtab.)
...

This message is not expected and is already a symptom.  Run it a second time, this time the index from the index-cache gets picked up.

$ ./gdb -nx --data-directory=data-directory -iex "set index-cache on" -iex "set sysroot /tmp/repro" /tmp/repro/gdb  /tmp/repro/core -ex bt -batch
...
/home/smarchi/src/binutils-gdb/gdb/dwarf2/read.c:5014: internal-error: compunit_symtab* dw2_find_pc_sect_compunit_symtab(objfile*, bound_minimal_symbol, CORE_ADDR, obj_section*, int): Assertion `result != NULL' failed.
...

Bisects to:

commit 9f6c202e573b796a9e7328cc5fdab7c0c63776bf                                                                                                                                                    
Author: Tom de Vries <tdevries@suse.de>                                                                                                                                                            
Date:   Mon Jan 25 16:32:31 2021 +0100                                                                                                                                                             

    [gdb/symtab] Handle DW_AT_ranges with DW_FORM_sec_off in partial DIE

The test binary happens to be a gdb executable I was trying to debug, but it doesn't really matter.  I generated a core from it to make the problem easy to reproduce.  I included only the necessary libraries from my system to allow reproducing.  They are from Arch Linux x86-64 packages:

 - libc-2.33.so from package glibc 2.33-5
 - libstdc++.so.6.0.29 from package gcc-libs 11.1.0-1

The main point is that libstdc++.so contains DWARF5 debug information, with DW_AT_ranges using DW_FORM_sec_offset form.  It looks like we are processing the ranges wrong when using the psymtab reader (hence the strange warning we get the first time).  And that makes us produce an invalid index in the cache, which, when we load the second time, confuses the GDB index reader.
Comment 1 Simon Marchi 2021-06-22 05:29:38 UTC
Here are the repro files (45MB): https://files.efficios.com/s/WYnRRzPRbbdbbMg
Comment 2 Tom de Vries 2021-06-25 12:47:08 UTC
The warning is caused by the fact that the addr map for the CU starts at 0, due to the DW_AT_entry_pc:
...
 <2><50bea>: Abbrev Number: 13 (DW_TAG_inlined_subroutine)
    <50beb>   DW_AT_abstract_origin: <0x50b99>
    <50bef>   DW_AT_entry_pc    : 0x0
    <50bf7>   DW_AT_GNU_entry_view: 0
    <50bf9>   DW_AT_ranges      : 0x3db4
    <50bfd>   DW_AT_call_file   : 1
    <50bfe>   DW_AT_call_line   : 64
    <50bff>   DW_AT_call_column : 9
    <50c00>   DW_AT_sibling     : <0x50c26>
...

Or, likewise, DW_AT_ranges:
...
0x00003db4: [DW_RLE_base_address]:  0x0000000000000000
0x00003dbd: [DW_RLE_offset_pair ]:  0x0000000000000000, 0x0000000000000007 => [0x0000000000000000, 0x0000000000000007)
0x00003dc0: [DW_RLE_offset_pair ]:  0x000000000000000b, 0x0000000000000018 => [0x000000000000000b, 0x0000000000000018)
0x00003dc3: [DW_RLE_end_of_list ]
...

Perhaps this is https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99654 .
Comment 3 Tom de Vries 2021-06-25 14:23:04 UTC
If I just start gdb with the shared lib, and print the address map I get a very reasonable:
...
(gdb) p /x map.transitions[0]
$16 = {addr = 0x0, value = 0x0}
(gdb) p /x map.transitions[1]
$17 = {addr = 0x99040, value = 0x1b236d0}
(gdb) p /x map.transitions[2]
$19 = {addr = 0x990bb, value = 0x0}
(gdb) p /x map.transitions[3]
$20 = {addr = 0x990bc, value = 0x1b236d0}
...
with 0x99040 being the start of the text segment:
...
Disassembly of section .text:

0000000000099040 <_ZNSi8ignoreXXEl.cold>:
   99040:       48 83 e8 01             sub    $0x1,%rax
   ...
   990bb:       90                      nop

00000000000990bc <_ZNSt13basic_istreamIwSt11char_traitsIwEE8ignoreXXEl.cold>:
...

But with the reproducer, I get:
...
(gdb) p /x map.transitions[0]
$30 = {addr = 0x0, value = 0x0}
(gdb) p /x map.transitions[1]
$31 = {addr = 0x0, value = 0x2deab60}
(gdb) p /x map.transitions[2]
$32 = {addr = 0x1d, value = 0x2591ce0}
(gdb) p /x map.transitions[3]
$33 = {addr = 0x4ef, value = 0x267bf00}
(gdb) p /x map.transitions[4]
$34 = {addr = 0xf72, value = 0x26c8ee0}
(gdb) p /x map.transitions[5]
$35 = {addr = 0x15eb, value = 0x0}
(gdb) p /x map.transitions[7]
$36 = {addr = 0x990bb, value = 0x0}
(gdb) p /x map.transitions[8]
$37 = {addr = 0x990bc, value = 0x1aced00}
...

Seems to be caused by this bit in dwarf2_rnglists_process:
...
      /* A not-uncommon case of bad debug info.                                               
         Don't pollute the addrmap with bad data.  */
      if (range_beginning + baseaddr == 0
          && !per_objfile->per_bfd->has_section_at_zero)
        {
          complaint (_(".debug_rnglists entry has start address of zero"
                       " [in module %s]"), objfile_name (objfile));
          continue;
        }
...
Comment 4 Tom de Vries 2021-06-25 14:30:03 UTC
This fixes the warning:
...
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 07bc08fba14..96bfb1280e1 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -13604,7 +13604,6 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu
,
   /* Base address selection entry.  */
   gdb::optional<CORE_ADDR> base;
   const gdb_byte *buffer;
-  CORE_ADDR baseaddr;
   bool overflow = false;
   ULONGEST addr_index;
   struct dwarf2_section_info *rnglists_section;
@@ -13621,8 +13620,6 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu
,
     }
   buffer = rnglists_section->buffer + offset;
 
-  baseaddr = objfile->text_section_offset ();
-
   while (1)
     {--
       /* Initialize it due to a false compiler warning.  */
@@ -13764,7 +13761,7 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu
,
 
       /* A not-uncommon case of bad debug info.
         Don't pollute the addrmap with bad data.  */
-      if (range_beginning + baseaddr == 0
+      if (range_beginning == 0
          && !per_objfile->per_bfd->has_section_at_zero)
        {
          complaint (_(".debug_rnglists entry has start address of zero"
...
which means we no longer trigger the assert when rerunning.  Doesn't fix the assert as such though.
Comment 5 Tom de Vries 2021-06-25 21:40:56 UTC
(In reply to Tom de Vries from comment #4)
> This fixes the warning:
> ...
> diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
> index 07bc08fba14..96bfb1280e1 100644
> --- a/gdb/dwarf2/read.c
> +++ b/gdb/dwarf2/read.c
> @@ -13604,7 +13604,6 @@ dwarf2_rnglists_process (unsigned offset, struct
> dwarf2_cu *cu
> ,
>    /* Base address selection entry.  */
>    gdb::optional<CORE_ADDR> base;
>    const gdb_byte *buffer;
> -  CORE_ADDR baseaddr;
>    bool overflow = false;
>    ULONGEST addr_index;
>    struct dwarf2_section_info *rnglists_section;
> @@ -13621,8 +13620,6 @@ dwarf2_rnglists_process (unsigned offset, struct
> dwarf2_cu *cu
> ,
>      }
>    buffer = rnglists_section->buffer + offset;
>  
> -  baseaddr = objfile->text_section_offset ();
> -
>    while (1)
>      {--
>        /* Initialize it due to a false compiler warning.  */
> @@ -13764,7 +13761,7 @@ dwarf2_rnglists_process (unsigned offset, struct
> dwarf2_cu *cu
> ,
>  
>        /* A not-uncommon case of bad debug info.
>          Don't pollute the addrmap with bad data.  */
> -      if (range_beginning + baseaddr == 0
> +      if (range_beginning == 0
>           && !per_objfile->per_bfd->has_section_at_zero)
>         {
>           complaint (_(".debug_rnglists entry has start address of zero"
> ...
> which means we no longer trigger the assert when rerunning.  Doesn't fix the
> assert as such though.

There's similar code for .debug_ranges.

I've tested a patch with both fixes on openSUSE Leap 15.2 x86_64 (gcc 7.5.0, using .debug_ranges), and on openSUSE Tumbleweed x86_64 (gcc 11.1.1, using .debug_rnglists).

/me -> vacation for 1 week.
Comment 6 Simon Marchi 2021-06-27 13:14:26 UTC
> I've tested a patch with both fixes on openSUSE Leap 15.2 x86_64 (gcc 7.5.0,
> using .debug_ranges), and on openSUSE Tumbleweed x86_64 (gcc 11.1.1, using
> .debug_rnglists).

I took a look, and I agree that adding baseaddr here does not make sense, if the goal is checking whether the range beginning is 0.

So in all these ranges generated by gcc:

             DW_AT_name [DW_FORM_line_strp]    ("/build/gcc/src/gcc/libstdc++-v3/src/c++98/bitmap_allocator.cc")
              DW_AT_comp_dir [DW_FORM_line_strp]        ("/build/gcc/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/src/c++98")
              DW_AT_ranges [DW_FORM_sec_offset] (0x00004b50
                 [0x0000000000000000, 0x0000000000000056)
                 [0x00000000000a4790, 0x00000000000a479c)
                 [0x00000000000a47a0, 0x00000000000a47ac)
                 [0x00000000000a47b0, 0x00000000000a47c8)
                 [0x0000000000000000, 0x0000000000000026)
                 [0x00000000000a47d0, 0x00000000000a47e8)
                 [0x0000000000000000, 0x0000000000000026)
                 [0x000000000009916c, 0x00000000000991a1)
                 [0x00000000000991a1, 0x00000000000991d6)
                 [0x00000000000b1e10, 0x00000000000b1e5b)
                 [0x0000000000000000, 0x0000000000000011)
                 [0x0000000000000000, 0x0000000000000011)

                 ...

All those starting from 0 are just bad and should not be considered?

> /me -> vacation for 1 week.

Hope you have a good time!
Comment 7 Tom de Vries 2021-07-26 16:17:46 UTC
(In reply to Simon Marchi from comment #6)
> > I've tested a patch with both fixes on openSUSE Leap 15.2 x86_64 (gcc 7.5.0,
> > using .debug_ranges), and on openSUSE Tumbleweed x86_64 (gcc 11.1.1, using
> > .debug_rnglists).
> 
> I took a look, and I agree that adding baseaddr here does not make sense, if
> the goal is checking whether the range beginning is 0.
> 

Ack.

> So in all these ranges generated by gcc:
> 
>              DW_AT_name [DW_FORM_line_strp]   
> ("/build/gcc/src/gcc/libstdc++-v3/src/c++98/bitmap_allocator.cc")
>               DW_AT_comp_dir [DW_FORM_line_strp]       
> ("/build/gcc/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/src/c++98")
>               DW_AT_ranges [DW_FORM_sec_offset] (0x00004b50
>                  [0x0000000000000000, 0x0000000000000056)
>                  [0x00000000000a4790, 0x00000000000a479c)
>                  [0x00000000000a47a0, 0x00000000000a47ac)
>                  [0x00000000000a47b0, 0x00000000000a47c8)
>                  [0x0000000000000000, 0x0000000000000026)
>                  [0x00000000000a47d0, 0x00000000000a47e8)
>                  [0x0000000000000000, 0x0000000000000026)
>                  [0x000000000009916c, 0x00000000000991a1)
>                  [0x00000000000991a1, 0x00000000000991d6)
>                  [0x00000000000b1e10, 0x00000000000b1e5b)
>                  [0x0000000000000000, 0x0000000000000011)
>                  [0x0000000000000000, 0x0000000000000011)
> 
>                  ...
> 
> All those starting from 0 are just bad and should not be considered?
> 

I guess so (The comment does mention that it's not uncommon).

> > /me -> vacation for 1 week.
> 
> Hope you have a good time!

I did :)

I've finally found time to work on the test-case and managed to create a dwarf assembly test-case for this (with .debug_ranges), so I'll probably submit the fix + test-case this week. [ Perhaps a .debug_rnglists version can be made easily as well, but I'll look into that after submission. ]
Comment 8 Simon Marchi 2021-07-29 19:19:18 UTC
(In reply to Tom de Vries from comment #7)
> I've finally found time to work on the test-case and managed to create a
> dwarf assembly test-case for this (with .debug_ranges), so I'll probably
> submit the fix + test-case this week. [ Perhaps a .debug_rnglists version
> can be made easily as well, but I'll look into that after submission. ]

Thanks, let me know if you'd like me to help adding the finishing touches to the fix and test, if you are caught up with other things.
Comment 9 Tom de Vries 2021-07-29 21:27:06 UTC
(In reply to Simon Marchi from comment #8)
> (In reply to Tom de Vries from comment #7)
> > I've finally found time to work on the test-case and managed to create a
> > dwarf assembly test-case for this (with .debug_ranges), so I'll probably
> > submit the fix + test-case this week. [ Perhaps a .debug_rnglists version
> > can be made easily as well, but I'll look into that after submission. ]
> 
> Thanks, let me know if you'd like me to help adding the finishing touches to
> the fix and test, if you are caught up with other things.

Thanks, I've just submitted ( https://sourceware.org/pipermail/gdb-patches/2021-July/181257.html ).

As mentioned before, this does not fix the assertion failure, so perhaps there's still time to look into that.  I might have time for that tomorrow.
Comment 10 Tom de Vries 2021-08-03 20:14:19 UTC
Actual root cause analysis:

The following warning / Internal error is reported:
...
$ gdb -q -batch \
    -iex "set sysroot $(pwd -P)/repro" \
    ./repro/gdb \
    ./repro/core \
    -ex bt
  ...
 Program terminated with signal SIGABRT, Aborted.
 #0  0x00007ff8fe8e5d22 in raise () from repro/usr/lib/libc.so.6
 [Current thread is 1 (LWP 1762498)]
 #1  0x00007ff8fe8cf862 in abort () from repro/usr/lib/libc.so.6
 warning: (Internal error: pc 0x7ff8feb2c21d in read in psymtab, \
           but not in symtab.)
 warning: (Internal error: pc 0x7ff8feb2c218 in read in psymtab, \
           but not in symtab.)
  ...
 #2  0x00007ff8feb2c21e in __gnu_debug::_Error_formatter::_M_error() const \
   [clone .cold] (warning: (Internal error: pc 0x7ff8feb2c21d in read in \
   psymtab, but not in symtab.)

) from repro/usr/lib/libstdc++.so.6
...

The warning is about the following:
- in find_pc_sect_compunit_symtab we try to find the address
  (0x7ff8feb2c218 / 0x7ff8feb2c21d) in the symtabs.
- that fails, so we try again in the partial symtabs.
- we find a matching partial symtab
- however, the partial symtab has a matching symtab, so
  we should have found a matching symtab in the first step.

The addresses are:
...
(gdb) info sym 0x7ff8feb2c218
__gnu_debug::_Error_formatter::_M_error() const [clone .cold] in \
  section .text of repro/usr/lib/libstdc++.so.6
(gdb) info sym 0x7ff8feb2c21d
__gnu_debug::_Error_formatter::_M_error() const [clone .cold] + 5 in \
  section .text of repro/usr/lib/libstdc++.so.6
...
which correspond to unrelocated addresses 0x9c218 and 0x9c21d:
...
$ nm -C  repro/usr/lib/libstdc++.so.6.0.29 | grep 000000000009c218
000000000009c218 t __gnu_debug::_Error_formatter::_M_error() const \
  [clone .cold]
...
which belong to function __gnu_debug::_Error_formatter::_M_error() in
/build/gcc/src/gcc/libstdc++-v3/src/c++11/debug.cc.

The partial symtab that is found for the addresses is instead the one for
/build/gcc/src/gcc/libstdc++-v3/src/c++98/bitmap_allocator.cc, which is
incorrect.

This happens due to this code in process_psymtab_comp_unit_reader being called
with cu_bounds_kind == PC_BOUNDS_INVALID, which sets the set_addrmap argument
to 1:
...
      scan_partial_symbols (first_die, &lowpc, &highpc,
                            cu_bounds_kind <= PC_BOUNDS_INVALID, cu);
...
and consequently, the addr_map get build using pc info from the functions [1].

During that process, addrmap_set_empty is called with a range that includes
0x9c218 and 0x9c21d:
...
(gdb) p /x start
$7 = 0x9989c
(gdb) p /x end_inclusive
$8 = 0xb200d
...
but it's called for a function at DIE 0x54153 with DW_AT_ranges at 0x40ae:
...
    000040ae 00000000000b1ee0 00000000000b200e
    000040b9 000000000009989c 00000000000998c4
    000040c3 <End of list>
...
which do not include 0x9c218 and 0x9c21d.

This is caused by this code:
...
            if (dwarf2_ranges_read (ranges_offset, &lowpc, &highpc, cu,
                                    nullptr, tag))
             has_pc_info = 1;
...
Disabling the has_pc_info assignment makes the warning go away.

[1] If we disable the code (in other words, we disable the workaround from PR
gdb/c++/15231 for a gcc-4.8 debug info problem):
...
-                            cu_bounds_kind <= PC_BOUNDS_INVALID, cu);
+                            cu_bounds_kind < PC_BOUNDS_INVALID, cu);
...
the warning disappears.
Comment 11 Tom de Vries 2021-08-04 14:19:22 UTC
(In reply to Simon Marchi from comment #0)
> Bisects to:
> 
> commit 9f6c202e573b796a9e7328cc5fdab7c0c63776bf                             
> Author: Tom de Vries <tdevries@suse.de>                                     
> Date:   Mon Jan 25 16:32:31 2021 +0100                                      
> 
>     [gdb/symtab] Handle DW_AT_ranges with DW_FORM_sec_off in partial DIE

And after carrying that patch during a further bisect, we get to:
...
commit 1b00ef063f8230a1f110cc5aeef04d3dc1338358
Author: Tom de Vries <tdevries@suse.de>
Date:   Wed Oct 28 21:04:12 2020 +0100

    [gdb/symtab] Fix language of frame without debug info
...

Which makes sense.  This is essentially the psymtab variant of the bug fixed in that commit for full symtabs.
Comment 12 Sourceware Commits 2021-08-06 14:44:22 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=b9f3fbc9f3453bcb24fece0c46acf581d13d3f64

commit b9f3fbc9f3453bcb24fece0c46acf581d13d3f64
Author: Tom de Vries <tdevries@suse.de>
Date:   Fri Aug 6 16:44:17 2021 +0200

    [gdb/symtab] Fix zero address complaint for shlib
    
    In PR28004 the following warning / Internal error is reported:
    ...
    $ gdb -q -batch \
        -iex "set sysroot $(pwd -P)/repro" \
        ./repro/gdb \
        ./repro/core \
        -ex bt
      ...
     Program terminated with signal SIGABRT, Aborted.
     #0  0x00007ff8fe8e5d22 in raise () from repro/usr/lib/libc.so.6
     [Current thread is 1 (LWP 1762498)]
     #1  0x00007ff8fe8cf862 in abort () from repro/usr/lib/libc.so.6
     warning: (Internal error: pc 0x7ff8feb2c21d in read in psymtab, \
               but not in symtab.)
     warning: (Internal error: pc 0x7ff8feb2c218 in read in psymtab, \
               but not in symtab.)
      ...
     #2  0x00007ff8feb2c21e in __gnu_debug::_Error_formatter::_M_error() const \
       [clone .cold] (warning: (Internal error: pc 0x7ff8feb2c21d in read in \
       psymtab, but not in symtab.)
    
    ) from repro/usr/lib/libstdc++.so.6
    ...
    
    The warning is about the following:
    - in find_pc_sect_compunit_symtab we try to find the address
      (0x7ff8feb2c218 / 0x7ff8feb2c21d) in the symtabs.
    - that fails, so we try again in the partial symtabs.
    - we find a matching partial symtab
    - however, the partial symtab has a full symtab, so
      we should have found a matching symtab in the first step.
    
    The addresses are:
    ...
    (gdb) info sym 0x7ff8feb2c218
    __gnu_debug::_Error_formatter::_M_error() const [clone .cold] in \
      section .text of repro/usr/lib/libstdc++.so.6
    (gdb) info sym 0x7ff8feb2c21d
    __gnu_debug::_Error_formatter::_M_error() const [clone .cold] + 5 in \
      section .text of repro/usr/lib/libstdc++.so.6
    ...
    which correspond to unrelocated addresses 0x9c218 and 0x9c21d:
    ...
    $ nm -C  repro/usr/lib/libstdc++.so.6.0.29 | grep 000000000009c218
    000000000009c218 t __gnu_debug::_Error_formatter::_M_error() const \
      [clone .cold]
    ...
    which belong to function __gnu_debug::_Error_formatter::_M_error() in
    /build/gcc/src/gcc/libstdc++-v3/src/c++11/debug.cc.
    
    The partial symtab that is found for the addresses is instead the one for
    /build/gcc/src/gcc/libstdc++-v3/src/c++98/bitmap_allocator.cc, which is
    incorrect.
    
    This happens as follows.
    
    The bitmap_allocator.cc CU has DW_AT_ranges at .debug_rnglist offset 0x4b50:
    ...
        00004b50 0000000000000000 0000000000000056
        00004b5a 00000000000a4790 00000000000a479c
        00004b64 00000000000a47a0 00000000000a47ac
    ...
    
    When reading the first range 0x0..0x56, it doesn't trigger the "start address
    of zero" complaint here:
    ...
          /* A not-uncommon case of bad debug info.
             Don't pollute the addrmap with bad data.  */
          if (range_beginning + baseaddr == 0
              && !per_objfile->per_bfd->has_section_at_zero)
            {
              complaint (_(".debug_rnglists entry has start address of zero"
                           " [in module %s]"), objfile_name (objfile));
              continue;
            }
    ...
    because baseaddr != 0, which seems incorrect given that when loading the
    shared library individually in gdb (and consequently baseaddr == 0), we do see
    the complaint.
    
    Consequently, we run into this case in dwarf2_get_pc_bounds:
    ...
      if (low == 0 && !per_objfile->per_bfd->has_section_at_zero)
        return PC_BOUNDS_INVALID;
    ...
    which then results in this code in process_psymtab_comp_unit_reader being
    called with cu_bounds_kind == PC_BOUNDS_INVALID, which sets the set_addrmap
    argument to 1:
    ...
          scan_partial_symbols (first_die, &lowpc, &highpc,
                                cu_bounds_kind <= PC_BOUNDS_INVALID, cu);
    ...
    and consequently, the CU addrmap gets build using address info from the
    functions.
    
    During that process, addrmap_set_empty is called with a range that includes
    0x9c218 and 0x9c21d:
    ...
    (gdb) p /x start
    $7 = 0x9989c
    (gdb) p /x end_inclusive
    $8 = 0xb200d
    ...
    but it's called for a function at DIE 0x54153 with DW_AT_ranges at 0x40ae:
    ...
        000040ae 00000000000b1ee0 00000000000b200e
        000040b9 000000000009989c 00000000000998c4
        000040c3 <End of list>
    ...
    and neither range includes 0x9c218 and 0x9c21d.
    
    This is caused by this code in partial_die_info::read:
    ...
                if (dwarf2_ranges_read (ranges_offset, &lowpc, &highpc, cu,
                                        nullptr, tag))
                 has_pc_info = 1;
    ...
    which pretends that the function is located at addresses 0x9989c..0xb200d,
    which is indeed not the case.
    
    This patch fixes the first problem encountered: fix the "start address of
    zero" complaint warning by removing the baseaddr part from the condition.
    Same for dwarf2_ranges_process.
    
    The effect is that:
    - the complaint is triggered, and
    - the warning / Internal error is no longer triggered.
    
    This does not fix the observed problem in partial_die_info::read, which is
    filed as PR28200.
    
    Tested on x86_64-linux.
    
    Co-Authored-By: Simon Marchi <simon.marchi@polymtl.ca>
    
    gdb/ChangeLog:
    
    2021-07-29  Simon Marchi  <simon.marchi@polymtl.ca>
                Tom de Vries  <tdevries@suse.de>
    
            PR symtab/28004
            * gdb/dwarf2/read.c (dwarf2_rnglists_process, dwarf2_ranges_process):
            Fix zero address complaint.
            * gdb/testsuite/gdb.dwarf2/dw2-zero-range-shlib.c: New test.
            * gdb/testsuite/gdb.dwarf2/dw2-zero-range.c: New test.
            * gdb/testsuite/gdb.dwarf2/dw2-zero-range.exp: New file.
Comment 13 Sourceware Commits 2021-08-06 16:02:33 UTC
The gdb-11-branch branch has been updated by Tom de Vries <vries@sourceware.org>:

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

commit a656ee0831bea07e57876aa933ce4fe2063c2355
Author: Tom de Vries <tdevries@suse.de>
Date:   Fri Aug 6 18:02:28 2021 +0200

    [gdb/symtab] Fix zero address complaint for shlib
    
    In PR28004 the following warning / Internal error is reported:
    ...
    $ gdb -q -batch \
        -iex "set sysroot $(pwd -P)/repro" \
        ./repro/gdb \
        ./repro/core \
        -ex bt
      ...
     Program terminated with signal SIGABRT, Aborted.
     #0  0x00007ff8fe8e5d22 in raise () from repro/usr/lib/libc.so.6
     [Current thread is 1 (LWP 1762498)]
     #1  0x00007ff8fe8cf862 in abort () from repro/usr/lib/libc.so.6
     warning: (Internal error: pc 0x7ff8feb2c21d in read in psymtab, \
               but not in symtab.)
     warning: (Internal error: pc 0x7ff8feb2c218 in read in psymtab, \
               but not in symtab.)
      ...
     #2  0x00007ff8feb2c21e in __gnu_debug::_Error_formatter::_M_error() const \
       [clone .cold] (warning: (Internal error: pc 0x7ff8feb2c21d in read in \
       psymtab, but not in symtab.)
    
    ) from repro/usr/lib/libstdc++.so.6
    ...
    
    The warning is about the following:
    - in find_pc_sect_compunit_symtab we try to find the address
      (0x7ff8feb2c218 / 0x7ff8feb2c21d) in the symtabs.
    - that fails, so we try again in the partial symtabs.
    - we find a matching partial symtab
    - however, the partial symtab has a full symtab, so
      we should have found a matching symtab in the first step.
    
    The addresses are:
    ...
    (gdb) info sym 0x7ff8feb2c218
    __gnu_debug::_Error_formatter::_M_error() const [clone .cold] in \
      section .text of repro/usr/lib/libstdc++.so.6
    (gdb) info sym 0x7ff8feb2c21d
    __gnu_debug::_Error_formatter::_M_error() const [clone .cold] + 5 in \
      section .text of repro/usr/lib/libstdc++.so.6
    ...
    which correspond to unrelocated addresses 0x9c218 and 0x9c21d:
    ...
    $ nm -C  repro/usr/lib/libstdc++.so.6.0.29 | grep 000000000009c218
    000000000009c218 t __gnu_debug::_Error_formatter::_M_error() const \
      [clone .cold]
    ...
    which belong to function __gnu_debug::_Error_formatter::_M_error() in
    /build/gcc/src/gcc/libstdc++-v3/src/c++11/debug.cc.
    
    The partial symtab that is found for the addresses is instead the one for
    /build/gcc/src/gcc/libstdc++-v3/src/c++98/bitmap_allocator.cc, which is
    incorrect.
    
    This happens as follows.
    
    The bitmap_allocator.cc CU has DW_AT_ranges at .debug_rnglist offset 0x4b50:
    ...
        00004b50 0000000000000000 0000000000000056
        00004b5a 00000000000a4790 00000000000a479c
        00004b64 00000000000a47a0 00000000000a47ac
    ...
    
    When reading the first range 0x0..0x56, it doesn't trigger the "start address
    of zero" complaint here:
    ...
          /* A not-uncommon case of bad debug info.
             Don't pollute the addrmap with bad data.  */
          if (range_beginning + baseaddr == 0
              && !per_objfile->per_bfd->has_section_at_zero)
            {
              complaint (_(".debug_rnglists entry has start address of zero"
                           " [in module %s]"), objfile_name (objfile));
              continue;
            }
    ...
    because baseaddr != 0, which seems incorrect given that when loading the
    shared library individually in gdb (and consequently baseaddr == 0), we do see
    the complaint.
    
    Consequently, we run into this case in dwarf2_get_pc_bounds:
    ...
      if (low == 0 && !per_objfile->per_bfd->has_section_at_zero)
        return PC_BOUNDS_INVALID;
    ...
    which then results in this code in process_psymtab_comp_unit_reader being
    called with cu_bounds_kind == PC_BOUNDS_INVALID, which sets the set_addrmap
    argument to 1:
    ...
          scan_partial_symbols (first_die, &lowpc, &highpc,
                                cu_bounds_kind <= PC_BOUNDS_INVALID, cu);
    ...
    and consequently, the CU addrmap gets build using address info from the
    functions.
    
    During that process, addrmap_set_empty is called with a range that includes
    0x9c218 and 0x9c21d:
    ...
    (gdb) p /x start
    $7 = 0x9989c
    (gdb) p /x end_inclusive
    $8 = 0xb200d
    ...
    but it's called for a function at DIE 0x54153 with DW_AT_ranges at 0x40ae:
    ...
        000040ae 00000000000b1ee0 00000000000b200e
        000040b9 000000000009989c 00000000000998c4
        000040c3 <End of list>
    ...
    and neither range includes 0x9c218 and 0x9c21d.
    
    This is caused by this code in partial_die_info::read:
    ...
                if (dwarf2_ranges_read (ranges_offset, &lowpc, &highpc, cu,
                                        nullptr, tag))
                 has_pc_info = 1;
    ...
    which pretends that the function is located at addresses 0x9989c..0xb200d,
    which is indeed not the case.
    
    This patch fixes the first problem encountered: fix the "start address of
    zero" complaint warning by removing the baseaddr part from the condition.
    Same for dwarf2_ranges_process.
    
    The effect is that:
    - the complaint is triggered, and
    - the warning / Internal error is no longer triggered.
    
    This does not fix the observed problem in partial_die_info::read, which is
    filed as PR28200.
    
    Tested on x86_64-linux.
    
    Co-Authored-By: Simon Marchi <simon.marchi@polymtl.ca>
    
    gdb/ChangeLog:
    
    2021-08-06  Simon Marchi  <simon.marchi@polymtl.ca>
                Tom de Vries  <tdevries@suse.de>
    
            PR symtab/28004
            * dwarf2/read.c (dwarf2_rnglists_process, dwarf2_ranges_process):
            Fix zero address complaint.
    
    gdb/testsuite/ChangeLog:
    
    2021-08-06  Simon Marchi  <simon.marchi@polymtl.ca>
                Tom de Vries  <tdevries@suse.de>
    
            PR symtab/28004
            * gdb.dwarf2/dw2-zero-range-shlib.c: New test.
            * gdb.dwarf2/dw2-zero-range.c: New test.
            * gdb.dwarf2/dw2-zero-range.exp: New file.
Comment 14 Tom de Vries 2021-08-06 16:05:06 UTC
Patch committed to master and gdb-11-branch.

Filed PR28200 for remaining issue.

Marking resolved-fixed.