Bug 26317 - GDB crashes when trying to insert a breakpoint by line number
Summary: GDB crashes when trying to insert a breakpoint by line number
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: gdb (show other bugs)
Version: HEAD
: P1 normal
Target Milestone: 11.1
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-07-29 17:12 UTC by Luis Machado
Modified: 2020-10-16 22:19 UTC (History)
3 users (show)

See Also:
Host: x86_64-linux-gnu;aarch64-linux-gnu
Target: x86_64-linux-gnu;aarch64-linux-gnu
Build: x86_64-linux-gnu;aarch64-linux-gnu
Last reconfirmed:


Attachments
test program (2.71 KB, application/x-sharedlib)
2020-07-29 17:12 UTC, Luis Machado
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Luis Machado 2020-07-29 17:12:44 UTC
Created attachment 12731 [details]
test program

Reproduction steps:

1 - Load the program (attached)
2 - Attempt to insert a breakpoint at line 27 with "b 27".

--

./gdb/gdb gdb/testsuite/outputs/gdb.dwarf2/dw2-line-number-zero/dw2-line-number-zero 
GNU gdb (GDB) 10.0.50.20200729-git
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from gdb/testsuite/outputs/gdb.dwarf2/dw2-line-number-zero/dw2-line-number-zero...
(gdb) b 27
zsh: abort (core dumped)  ./gdb/gdb 

--

Backtrace of the crash:

--
#0  0x00005555557ef903 in create_sals_line_offset (ls=0x7fffffffd970, self=0x7fffffffd920, this=<optimized out>) at ../../../repos/binutils-gdb/gdb/linespec.c:2105
#1  convert_linespec_to_sals (state=state@entry=0x7fffffffd920, ls=ls@entry=0x7fffffffd970) at ../../../repos/binutils-gdb/gdb/linespec.c:2338
#2  0x00005555557f234e in parse_linespec (parser=parser@entry=0x7fffffffd8f0, arg=<optimized out>, match_type=<optimized out>) at ../../../repos/binutils-gdb/gdb/linespec.c:2693
#3  0x00005555557f2e4d in event_location_to_sals (parser=parser@entry=0x7fffffffd8f0, location=location@entry=0x555556234dd0) at ../../../repos/binutils-gdb/gdb/linespec.c:3150
#4  0x00005555557f31dc in decode_line_full (
During symbol reading, No DW_FORM_block* DW_AT_call_value for DW_TAG_call_site child DIE 0x51ce53 [in module /home/lgmachado/work/linaro/tcwg/builds/binutils-gdb-master/gdb/gdb].
location=location@entry=0x555556234dd0, flags=flags@entry=1, search_pspace=search_pspace@entry=0x0, default_symtab=<optimized out>, default_line=<optimized out>, canonical=0x7fffffffdc40, select_mode=0x0, filter=<optimized out>) at ../../../repos/binutils-gdb/gdb/linespec.c:3230
#5  0x0000555555691455 in parse_breakpoint_sals (location=0x555556234dd0, canonical=0x7fffffffdc40) at ../../../repos/binutils-gdb/gdb/breakpoint.c:9028
#6  0x0000555555696c3f in create_breakpoint (gdbarch=0x55555621bbd0, location=location@entry=0x555556234dd0, cond_string=cond_string@entry=0x0, thread=<optimized out>, thread@entry=0, extra_string=0x0, extra_string@entry=0x555556008f84 "", parse_extra=parse_extra@entry=1, tempflag=0, type_wanted=bp_breakpoint, 
    ignore_count=0, pending_break_support=AUTO_BOOLEAN_AUTO, ops=0x555555fcd5e0 <bkpt_breakpoint_ops>, from_tty=1, enabled=1, internal=0, flags=0) at ../../../repos/binutils-gdb/gdb/breakpoint.c:9244
#7  0x00005555556973ce in break_command_1 (arg=<optimized out>, flag=<optimized out>, from_tty=1) at ../../../repos/binutils-gdb/gdb/breakpoint.c:9402
#8  0x00005555556c39c2 in cmd_func (cmd=<optimized out>, args=<optimized out>, from_tty=<optimized out>) at ../../../repos/binutils-gdb/gdb/cli/cli-decode.c:2181
#9  0x0000555555953558 in execute_command (p=<optimized out>, p@entry=0x555556008f80 "b 27", from_tty=1) at ../../../repos/binutils-gdb/gdb/top.c:668
#10 0x0000555555777afc in command_handler (command=0x555556008f80 "b 27") at ../../../repos/binutils-gdb/gdb/event-top.c:588
#11 0x0000555555777e9d in command_line_handler (rl=...) at ../../../repos/binutils-gdb/gdb/event-top.c:773
#12 0x0000555555778409 in gdb_rl_callback_handler (rl=0x555556234d30 "b 27") at ../../../repos/binutils-gdb/gdb/event-top.c:219
#13 0x00005555559d56c7 in rl_callback_read_char () at ../../../../repos/binutils-gdb/readline/readline/callback.c:281
#14 0x00005555557770d6 in gdb_rl_callback_read_char_wrapper_noexcept () at ../../../repos/binutils-gdb/gdb/event-top.c:177
#15 0x00005555557782c0 in gdb_rl_callback_read_char_wrapper (client_data=<optimized out>) at ../../../repos/binutils-gdb/gdb/event-top.c:194
#16 0x0000555555776f30 in stdin_event_handler (error=<optimized out>, client_data=0x555556008c70) at ../../../repos/binutils-gdb/gdb/event-top.c:516
#17 0x0000555555a9f11d in gdb_wait_for_event (block=block@entry=1) at ../../../repos/binutils-gdb/gdbsupport/event-loop.cc:673
#18 0x0000555555a9f2e1 in gdb_do_one_event () at ../../../repos/binutils-gdb/gdbsupport/event-loop.cc:215
#19 0x000055555581e7cd in start_event_loop () at ../../../repos/binutils-gdb/gdb/main.c:356
#20 captured_command_loop () at ../../../repos/binutils-gdb/gdb/main.c:416
#21 0x00005555558208a5 in captured_main (data=<optimized out>) at ../../../repos/binutils-gdb/gdb/main.c:1253
#22 gdb_main (args=<optimized out>) at ../../../repos/binutils-gdb/gdb/main.c:1268
#23 0x000055555562c62b in main (argc=<optimized out>, argv=<optimized out>) at ../../../repos/binutils-gdb/gdb/gdb.c:32
Comment 1 Luis Machado 2020-07-29 17:19:18 UTC
We crash because we're trying to access self->default_symtab->filename, but self->default_symtab is a nullptr.

This particular section was touched by commit bb995d00b3eef2f48d0be895c3509a7ddd8280a1.

commit bb995d00b3eef2f48d0be895c3509a7ddd8280a1
Author: Keith Seitz <keiths@redhat.com>
Date:   Fri Feb 22 09:39:35 2019 -0800

    Fix symtab/23853: symlinked default symtab


It looks like we're missing a nullptr check somewhere.
Comment 2 Keith Seitz 2020-07-29 19:26:23 UTC
(In reply to Luis Machado from comment #1)
> We crash because we're trying to access self->default_symtab->filename, but
> self->default_symtab is a nullptr.
> 
> This particular section was touched by commit
> bb995d00b3eef2f48d0be895c3509a7ddd8280a1.
> 
> commit bb995d00b3eef2f48d0be895c3509a7ddd8280a1
> Author: Keith Seitz <keiths@redhat.com>
> Date:   Fri Feb 22 09:39:35 2019 -0800
> 
>     Fix symtab/23853: symlinked default symtab

Actually, if you checkout 1dd58850778^^^^^ (because of build errors aruond
commit 1dd58850778), this works:

$. /gdb -q ~/Downloads/dw2-line-number-zero -ex "b 27"
Reading symbols from /home/keiths/Downloads/dw2-line-number-zero...
Breakpoint 1 at 0x608: file /home/lgmachado/work/linaro/tcwg/builds/binutils-gdb-master/gdb/testsuite/../../../../repos/binutils-gdb/gdb/testsuite/gdb.dwarf2/dw2-line-number-zero.c, line 27.

With commit 1dd58850778:

$ ./gdb -q ~/Downloads/dw2-line-number-zero -ex "b 27"
Reading symbols from /home/keiths/Downloads/dw2-line-number-zero...
Segmentation fault (core dumped)
Comment 3 Luis Machado 2020-07-30 12:18:39 UTC
Are you saying commit 1dd58850778 is the one we should be looking at? If so, we should CC Tromey.
Comment 4 Tom Tromey 2020-07-30 20:11:34 UTC
find_function_start_sal is returning a sal that has a symbol
but no symtab, which seems wrong.
Comment 5 Tom Tromey 2020-07-30 20:15:37 UTC
This worked for me but I am not sure about it.

diff --git a/gdb/symtab.c b/gdb/symtab.c
index f96ad9554d9..38af2482e95 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -3666,6 +3666,8 @@ find_function_start_sal (CORE_ADDR func_addr, obj_section *section,
      the symtab and linenumber, but not a symbol.  Fill in the
      function symbol too.  */
   sal.symbol = find_pc_sect_containing_function (sal.pc, sal.section);
+  if (sal.symtab == nullptr)
+    sal.symtab = symbol_symtab (sal.symbol);
 
   return sal;
 }
@@ -3681,6 +3683,8 @@ find_function_start_sal (symbol *sym, bool funfirstline)
 				 SYMBOL_OBJ_SECTION (symbol_objfile (sym), sym),
 				 funfirstline);
   sal.symbol = sym;
+  if (sal.symtab == nullptr)
+    sal.symtab = symbol_symtab (sal.symbol);
   return sal;
 }
Comment 6 Tom Tromey 2020-07-30 20:17:01 UTC
... for one thing, I hate to add new uses of symbol_symtab,
just on the principle that back-links are bad.  (Terrible reason.)
However it might be better to do the assignment elsewhere,
or to have things like find_pc_sect_containing_function
return a {symbol,symtab} pair.
Comment 7 Tom de Vries 2020-08-03 07:25:26 UTC
(In reply to Tom Tromey from comment #4)
> find_function_start_sal is returning a sal that has a symbol
> but no symtab, which seems wrong.

FTR.

When find_function_start_sal is called we have backtrace:
...
(gdb) bt
#0  find_function_start_sal (sym=0x223ae40, funfirstline=true)
    at src/gdb/symtab.c:3678
#1  0x000000000096f467 in select_source_symtab (s=0x0)
    at src/gdb/source.c:308
#2  0x000000000096f285 in set_default_source_symtab_and_line ()
    at src/gdb/source.c:248
#3  0x000000000074c570 in create_sals_line_offset (self=0x7fffffffcfb0, ls=0x7fffffffd000)
    at src/gdb/linespec.c:2102
#4  0x000000000074d468 in convert_linespec_to_sals (state=0x7fffffffcfb0, ls=0x7fffffffd000)
    at src/gdb/linespec.c:2338
#5  0x000000000074e146 in parse_linespec (parser=0x7fffffffcf80, arg=0x220f870 "27", 
    match_type=symbol_name_match_type::WILD)
...
and sym:
...
(gdb) p sym.m_name
$9 = 0x220eed1 "main"
...

That is, we're trying to set a breakpoint at line 27 in function bar1, but in the process we're trying to find the function start for main.

I've compiled dw2-line-number-zero.c with -g, and got the same behaviour, so that's not something specific to this dwarf assembly test-case.

Anyway, in find_pc_sect_line we're trying to find the sal for the address of main, and iterate over compunit_filesymtabs to find the 'best' matching symtab give the line number info, but no matching symtab is found because there's no line info for main in the dwarf assembly test-case, so we hit this case:
...
  if (!best_symtab)
    {
      /* If we didn't find any line number info, just return zeros.                           
         We used to return alt->line - 1 here, but that could be                              
         anywhere; if we don't have line number info for this PC,                             
         don't make some up.  */
      val.pc = pc;
    }
...

So, this problem can be worked around by adding that missing line number info:
...
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-line-number-zero.c b/gdb/testsuite/gdb.dwarf2/dw2
-line-number-zero.c
index 15b37a6676..ac7e306aa3 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-line-number-zero.c
+++ b/gdb/testsuite/gdb.dwarf2/dw2-line-number-zero.c
@@ -57,6 +57,7 @@ main (void)
 
   bar2 ();
 
+  asm ("main_label_2: .globl main_label_2");
   return 0;
 }
 
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-line-number-zero.exp b/gdb/testsuite/gdb.dwarf2/d
w2-line-number-zero.exp
index 12011b5f9c..66566752f0 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-line-number-zero.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-line-number-zero.exp
@@ -102,6 +102,13 @@ Dwarf::assemble $asm_file {
 
            {DW_LNE_set_address bar2_label_5}
            {DW_LNE_end_sequence}
+
+           {DW_LNE_set_address main_label}
+           {line 54}
+           {DW_LNS_copy}
+
+           {DW_LNE_set_address main_label_2}
+           {DW_LNE_end_sequence}
        }
     }
 }
...
Comment 8 Tom de Vries 2020-08-03 08:04:52 UTC
(In reply to Tom Tromey from comment #6)
> ... for one thing, I hate to add new uses of symbol_symtab,
> just on the principle that back-links are bad.  (Terrible reason.)
> However it might be better to do the assignment elsewhere,
> or to have things like find_pc_sect_containing_function
> return a {symbol,symtab} pair.

This fixes things at the find_function_start_sal use site instead (but still uses the back-link):
...
diff --git a/gdb/source.c b/gdb/source.c
index 0c2b5a4f83..8e082b3017 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -306,7 +306,12 @@ select_source_symtab (struct symtab *s)
   if (bsym.symbol != nullptr && SYMBOL_CLASS (bsym.symbol) == LOC_BLOCK)
     {
       symtab_and_line sal = find_function_start_sal (bsym.symbol, true);
-      loc->set (sal.symtab, std::max (sal.line - (lines_to_list - 1), 1));
+      if (sal.symtab == NULL)
+       /* We couldn't find the location of `main', possibly due to missing
+          line number info, fall back to line 1 in the corresponding file.  */
+       loc->set (symbol_symtab (bsym.symbol), 1);
+      else
+       loc->set (sal.symtab, std::max (sal.line - (lines_to_list - 1), 1));
       return;
     }
 
...
Comment 9 Tom de Vries 2020-08-03 08:10:46 UTC
FWIW, test-case for this PR:
...
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-line-number-zero.exp b/gdb/testsuite/gdb.dwarf2/d
w2-line-number-zero.exp
index 12011b5f9c..6404ac62e2 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-line-number-zero.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-line-number-zero.exp
@@ -115,7 +115,7 @@ if ![runto_main] {
     return -1
 }
 
-gdb_breakpoint "$srcfile:27"
+gdb_breakpoint "27"
 gdb_continue_to_breakpoint "bar1" "\[^\r\n\]*:27\r\n.*"
 
 gdb_test "n" "foo \\(2\\);" "bar1, 1st next"
...
Comment 10 Tom de Vries 2020-10-16 14:00:41 UTC
Submitted patch: https://sourceware.org/pipermail/gdb-patches/2020-October/172580.html
Comment 11 Sourceware Commits 2020-10-16 22:10:41 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=520596f2eb7430dca76d887dc6c39698654af728

commit 520596f2eb7430dca76d887dc6c39698654af728
Author: Tom de Vries <tdevries@suse.de>
Date:   Sat Oct 17 00:10:31 2020 +0200

    [gdb/symtab] Handle setting line bp without debug line info
    
    When setting a breakpoint on a line in an executable without debug line info,
    we run into an abort.
    
    The problem occurs when calling set_default_source_symtab_and_line, which
    calls select_source_symtab (0), which is where we try to find the line number
    for main:
    ...
      /* Make the default place to list be the function `main'
         if one exists.  */
      block_symbol bsym = lookup_symbol (main_name (), 0, VAR_DOMAIN, 0);
      if (bsym.symbol != nullptr && SYMBOL_CLASS (bsym.symbol) == LOC_BLOCK)
        {
          symtab_and_line sal = find_function_start_sal (bsym.symbol, true);
          loc->set (sal.symtab, std::max (sal.line - (lines_to_list - 1), 1));
          return;
        }
    ...
    
    However, due to the missing debug line info, find_function_start_sal returns a
    sal with sal.symtab == 0:
    ...
    (gdb) p /x sal
    $2 = {pspace = 0x1a4a7f0, symtab = 0x0, symbol = 0x1d9e480, section = 0x1d5b398,
      msymbol = 0x0, line = 0x0, pc = 0x4004ab, end = 0x0, explicit_pc = 0x0,
      explicit_line = 0x0, is_stmt = 0x0, prob = 0x0, objfile = 0x0}
    ...
    which eventually causes an segfault in create_sals_line_offset because
    self->default_symtab->filename is accessed while self->default_symtab == NULL.
    
    Fix this by handling sal.symtab == NULL in select_source_symtab.
    
    Tested on x86_64-linux.
    
    gdb/ChangeLog:
    
    2020-10-17  Tom de Vries  <tdevries@suse.de>
    
            PR symtab/26317
            * source.c (select_source_symtab): Handling sal.symtab == NULL for
            symbol main.
    
    gdb/testsuite/ChangeLog:
    
    2020-10-17  Tom de Vries  <tdevries@suse.de>
    
            PR symtab/26317
            * gdb.dwarf2/dw2-main-no-line-number.exp: New file.
Comment 12 Tom de Vries 2020-10-16 22:19:31 UTC
Patch with test-case committed, marking resolved-fixed.