Bug 20020

Summary: GDB segfault on printing objects
Product: gdb Reporter: Thilo Voertler <thilo.voertler>
Component: c++Assignee: Tom Tromey <tromey>
Status: RESOLVED FIXED    
Severity: critical CC: 3maisons, adrian.harris, anton_nix, bob.steagall.cpp, brobecker, bryanmcsp, carlo, christian.klein, cristiano, damir.franusic, eldar.abusalimov, guillaume, hfuvre+ce22i7qsq5k3w, keiths, mark, mehmetgelisin, nolange79, oxyd.oxyd, ppluzhnikov, rafael, snyder, thilo.voertler, thomas, thomas, tromey, ucelsanicin, weimin.pan, yuras
Priority: P2    
Version: 7.11.1   
Target Milestone: 8.3.1   
Host: Target:
Build: Last reconfirmed:
Attachments: sca_port_base

Description Thilo Voertler 2016-04-29 10:21:33 UTC
Created attachment 9223 [details]
sca_port_base

When printing an object of the type sca_port_base - part of the Open Source SystemC AMS Simulator - gdb versions newer than > 7.6.1 crash (Linux and MinGW64  versions). Below you find the backtrace when debugging gdb 7.11. The error occurs in value.c of gdb

We can provide also an executable to reproduce the crash, however it is quite large, due to the libraries required. Attached you find the source code of the object which is tried to be printed. GDB commands executed in the session are just: 

b my_first_sch_simple_tb.cpp:128
r
print i_conv_1.tdf_i
---
Breakpoint 1, sc_main (argc=<optimized out>, argv=<optimized out>) at hier_modules/my_first_sch_simple_tb.cpp:139
139         dut = new my_first_sch("dut", p_dut);
(gdb) print i_conv_1.tdf_i
$1 = {<sca_tdf::sca_implementation::sca_tdf_port_impl<sca_tdf::sca_signal_if<double>, double>> = {<sca_core::sca_port<sca_tdf::sca_signal_if<double> >> = {<sca_core::sca_implementation::sca_port_impl<sca_tdf::sca_signal_if<double> >> = {<sc_core::sc_port<sc                                                           a_tdf::sca_signal_if<double>, 1, (sc_core::sc_port_policy)0>> = {<sc_core::sc_port_b<sca_tdf::sca_signal_if<double> >> = {<sc_core::sc_port_base> = {<sc_core::sc_object> = {_vptr.sc_object = 0x7e5310 <vtable for sca_tdf::sca_in<double>+16>, 
                m_attr_cltn_p = 0x0, m_child_events = {<std::_Vector_base<sc_core::sc_event*, std::allocator<sc_core::sc_event*> >> = {
                    _M_impl = {<std::allocator<sc_core::sc_event*>> = {<__gnu_cxx::new_allocator<sc_core::sc_event*>> = {<No data fields>}, <No data fields>}, _M_start = 0x0, _M_finish = 0x0, _M_end_of_storage = 0x0}}, <No data fields>}, 
                m_child_objects = {<std::_Vector_base<sc_core::sc_object*, std::allocator<sc_core::sc_object*> >> = {
                    _M_impl = {<std::allocator<sc_core::sc_object*>> = {<__gnu_cxx::new_allocator<sc_core::sc_object*>> = {<No data fields>}, <No data fields>}, _M_start = 0x0, _M_finish = 0x0, _M_end_of_storage = 0x0}}, <No data fields>}, m_name = {
                  static npos = <optimized out>, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x825808 "i_conv_1.tdf_i"}}, m_parent = 0x7fffffffb3f0, m_simc = 0x7f9090}, 
              m_bind_info = 0x8258b0}, m_interface = 0x7fffffffabe0, m_interface_vec = {<std::_Vector_base<sca_tdf::sca_signal_if<double>*, std::allocator<sca_tdf::sca_signal_if<double>*> >> = {
                _M_impl = {<std::allocator<sca_tdf::sca_signal_if<double>*>> = {<__gnu_cxx::new_allocator<sca_tdf::sca_signal_if<double>*>> = {<No data fields>}, <No data fields>}, _M_start = 0x825a30, _M_finish = 0x825a38, 
                  _M_end_of_storage = 0x825a38}}, <No data fields>}}, <No data fields>}, <sca_core::sca_implementation::sca_port_base> = {<sca_util::sca_traceable_object> = {_vptr.sca_traceable_object = 0x7e5448 <vtable for sca_tdf::sca_in<double>+328>, 
            empty_string = {static npos = <optimized out>, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x7ffff7fec6b8 <std::string::_Rep::_S_empty_rep_storage+24> ""}}, unit = {
              static npos = <optimized out>, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x7ffff7fec6b8 <std::string::_Rep::_S_empty_rep_storage+24> ""}}, unit_prefix = {
              static npos = <optimized out>, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x7ffff7fec6b8 <std::string::_Rep::_S_empty_rep_storage+24> ""}}, domain = {
              static npos = <optimized out>, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x7ffff7fec6b8 <std::string::_Rep::_S_empty_rep_storage+24> ""}}}, 
          elaboration_finished = false, sca_port_type = sca_core::sca_implementation::sca_port_base::SCA_IN_PORT, port_number = 0, port_if_id = 0, parent_module = 0x7fffffffb3f0, m_if = 0x0, m_sca_if = 0x0, port_elaborated = false}, 

Program received signal SIGSEGV, Segmentation fault.
0x000000000052910c in value_entirely_covered_by_range_vector (value=0x0, ranges=0x80) at ../../gdb/value.c:398
398       if (value->lazy)
(gdb) bt
#0  0x000000000052910c in value_entirely_covered_by_range_vector (value=0x0, ranges=0x80) at ../../gdb/value.c:398
#1  0x00000000005291e0 in value_entirely_optimized_out (value=0x0) at ../../gdb/value.c:423
#2  0x00000000006ab132 in cp_print_static_field (type=0x2091f20, val=0x0, stream=0xde3930, recurse=4, options=0x7fffffffb520) at ../../gdb/cp-valprint.c:641
#3  0x00000000006aa211 in cp_print_value_fields (type=0x21b0de0, real_type=0x21e49e0, valaddr=0x409c670 "\020S~", offset=0, address=140737488336456, stream=0xde3930, recurse=3, val=0x1dd2f00, options=0x7fffffffb520, dont_print_vb=0xdc12c0, 
    dont_print_statmem=0) at ../../gdb/cp-valprint.c:331
#4  0x00000000006aaf9d in cp_print_value (type=0x21b8c50, real_type=0x21e49e0, valaddr=0x409c670 "\020S~", offset=0, address=140737488336456, stream=0xde3930, recurse=3, val=0x1dd2f00, options=0x7fffffffb520, dont_print_vb=0xdc12c0)
    at ../../gdb/cp-valprint.c:599
#5  0x00000000006a9a9c in cp_print_value_fields (type=0x21b8c50, real_type=0x21e49e0, valaddr=0x409c670 "\020S~", offset=0, address=140737488336456, stream=0xde3930, recurse=2, val=0x1dd2f00, options=0x7fffffffb520, dont_print_vb=0xdc12c0, 
    dont_print_statmem=0) at ../../gdb/cp-valprint.c:197
#6  0x00000000006aaf9d in cp_print_value (type=0x21dcbf0, real_type=0x21e49e0, valaddr=0x409c670 "\020S~", offset=0, address=140737488336456, stream=0xde3930, recurse=2, val=0x1dd2f00, options=0x7fffffffb520, dont_print_vb=0xdc12c0)
    at ../../gdb/cp-valprint.c:599
#7  0x00000000006a9a9c in cp_print_value_fields (type=0x21dcbf0, real_type=0x21e49e0, valaddr=0x409c670 "\020S~", offset=0, address=140737488336456, stream=0xde3930, recurse=1, val=0x1dd2f00, options=0x7fffffffb520, dont_print_vb=0xdc12c0, 
    dont_print_statmem=0) at ../../gdb/cp-valprint.c:197
#8  0x00000000006aaf9d in cp_print_value (type=0x21e49e0, real_type=0x21e49e0, valaddr=0x409c670 "\020S~", offset=0, address=140737488336456, stream=0xde3930, recurse=1, val=0x1dd2f00, options=0x7fffffffb520, dont_print_vb=0x0)
    at ../../gdb/cp-valprint.c:599
#9  0x00000000006a9a9c in cp_print_value_fields (type=0x21e49e0, real_type=0x21e49e0, valaddr=0x409c670 "\020S~", offset=0, address=140737488336456, stream=0xde3930, recurse=0, val=0x1dd2f00, options=0x7fffffffb520, dont_print_vb=0x0, 
    dont_print_statmem=0) at ../../gdb/cp-valprint.c:197
#10 0x00000000006aa766 in cp_print_value_fields_rtti (type=0x21e49e0, valaddr=0x409c670 "\020S~", offset=0, address=140737488336456, stream=0xde3930, recurse=0, val=0x1dd2f00, options=0x7fffffffb520, dont_print_vb=0x0, dont_print_statmem=0)
    at ../../gdb/cp-valprint.c:452
#11 0x00000000006a8c06 in c_val_print_struct (type=0x21e49e0, valaddr=0x409c670 "\020S~", embedded_offset=0, address=140737488336456, stream=0xde3930, recurse=0, original_value=0x1dd2f00, options=0x7fffffffb520) at ../../gdb/c-valprint.c:406
#12 0x00000000006a9012 in c_val_print (type=0x21e49e0, valaddr=0x409c670 "\020S~", embedded_offset=0, address=140737488336456, stream=0xde3930, recurse=0, original_value=0x1dd2f00, options=0x7fffffffb520) at ../../gdb/c-valprint.c:526
#13 0x00000000005464fa in val_print (type=0x21e49e0, valaddr=0x409c670 "\020S~", embedded_offset=0, address=140737488336456, stream=0xde3930, recurse=0, val=0x1dd2f00, options=0x7fffffffb5e0, language=0x8f4e00 <cplus_language_defn>)
    at ../../gdb/valprint.c:1009
#14 0x00000000006a966a in c_value_print (val=0x1dd2f00, stream=0xde3930, options=0x7fffffffb760) at ../../gdb/c-valprint.c:689
#15 0x00000000005468b9 in value_print (val=0x1dd2f00, stream=0xde3930, options=0x7fffffffb760) at ../../gdb/valprint.c:1125
#16 0x000000000054b0cc in print_formatted (val=0x1dd2f00, size=0, options=0x7fffffffb760, stream=0xde3930) at ../../gdb/printcmd.c:315
#17 0x000000000054c5dd in print_value (val=0x1dd2f00, fmtp=0x7fffffffb7d0) at ../../gdb/printcmd.c:976
#18 0x000000000054c6c7 in print_command_1 (exp=0xd0d276 "i_conv_1.tdf_i", voidprint=1) at ../../gdb/printcmd.c:1007
#19 0x000000000054c6f5 in print_command (exp=0xd0d276 "i_conv_1.tdf_i", from_tty=1) at ../../gdb/printcmd.c:1015
#20 0x00000000004a3e0d in do_cfunc (c=0xd8eb80, args=0xd0d276 "i_conv_1.tdf_i", from_tty=1) at ../../gdb/cli/cli-decode.c:105
#21 0x00000000004a6d88 in cmd_func (cmd=0xd8eb80, args=0xd0d276 "i_conv_1.tdf_i", from_tty=1) at ../../gdb/cli/cli-decode.c:1885
#22 0x00000000006bb251 in execute_command (p=0xd0d283 "i", from_tty=1) at ../../gdb/top.c:475
#23 0x00000000005a9027 in command_handler (command=0xd0d270 "print i_conv_1.tdf_i") at ../../gdb/event-top.c:491
#24 0x00000000005a95e4 in command_line_handler (rl=0xf46320 "") at ../../gdb/event-top.c:690
#25 0x000000000072362f in rl_callback_read_char () at ../../readline/callback.c:220
#26 0x00000000005a8af8 in rl_callback_read_char_wrapper (client_data=0x0) at ../../gdb/event-top.c:171
#27 0x00000000005a8f57 in stdin_event_handler (error=0, client_data=0x0) at ../../gdb/event-top.c:430
#28 0x00000000005a7ba5 in handle_file_event (file_ptr=0xf4ee10, ready_mask=1) at ../../gdb/event-loop.c:708
#29 0x00000000005a8143 in gdb_wait_for_event (block=1) at ../../gdb/event-loop.c:834
#30 0x00000000005a70b4 in gdb_do_one_event () at ../../gdb/event-loop.c:323
#31 0x00000000005a70f8 in start_event_loop () at ../../gdb/event-loop.c:347
#32 0x00000000005a8b2a in cli_command_loop (data=0x0) at ../../gdb/event-top.c:186
#33 0x000000000059fc28 in current_interp_command_loop () at ../../gdb/interps.c:317
#34 0x00000000005a073e in captured_command_loop (data=0x0) at ../../gdb/main.c:318
#35 0x000000000059ca44 in catch_errors (func=0x5a0723 <captured_command_loop>, func_args=0x0, errstring=0x8bb1ba "", mask=RETURN_MASK_ALL) at ../../gdb/exceptions.c:240
#36 0x00000000005a1be0 in captured_main (data=0x7fffffffbd80) at ../../gdb/main.c:1157
#37 0x000000000059ca44 in catch_errors (func=0x5a0b58 <captured_main>, func_args=0x7fffffffbd80, errstring=0x8bb1ba "", mask=RETURN_MASK_ALL) at ../../gdb/exceptions.c:240
#38 0x00000000005a1c09 in gdb_main (args=0x7fffffffbd80) at ../../gdb/main.c:1165
#39 0x0000000000405c0d in main (argc=2, argv=0x7fffffffbe88) at ../../gdb/gdb.c:32
(gdb)
Comment 1 Thilo Voertler 2016-06-29 13:42:16 UTC
We had some time for looking into this bug and found the reason for this error seems to be that v in cp-valprint.c:316 can be NULL when the TRY-CATCH is triggered and therefore v never gets assigned. The function cp_print_static_field doesn't check that the passed v is NULL.

  struct value *v = NULL;                                 
                                                          
  TRY                                                     
    {                                                     
      v = value_static_field (type, i);                   
    }                                                     
                                                          
  CATCH (ex, RETURN_MASK_ERROR)                           
    {                                                     
      fprintf_filtered (stream,                           
			_("<error reading variable: %s>"),            
			ex.message);                                  
    }                                                     
  END_CATCH                                               
                                 
	  cp_print_static_field (TYPE_FIELD_TYPE (type, i),   
			 v, stream, recurse + 1,                      
			 options);                                    

We looked into the commit history and there used to be a check that after the exception was thrown v is not NULL. Therefore I would propose the following patch.

  struct value *v = NULL;                               
                                                        
  TRY                                                   
    {                                                   
      v = value_static_field (type, i);                 
    }                                                   
                                                        
  CATCH (ex, RETURN_MASK_ERROR)                         
    {                                                   
      fprintf_filtered (stream,                         
			_("<error reading variable: %s>"),          
			ex.message);                                
      v = NULL; // In case v was already modified       
    }                                                   
  END_CATCH                                             
                                                        
  if (v !=NULL ) {                                      
                                                        
	  cp_print_static_field (TYPE_FIELD_TYPE (type, i), 
			 v, stream, recurse + 1,                    
			 options);                                  
  }                                                                                    

Any comment would be appreciated

Best Regards, 

Thilo
Comment 2 Guillaume Morin 2017-08-02 18:24:26 UTC
We have started experiencing a similar crash when we switched to g++ 7.1 with c++17 semantics.  When gdb tries to print a "static constexpr", it triggers a "error reading variable: Missing ELF symbol" exception and then crashes at the same place as the original reporter. This seems to happen with every release at least from gdb 7.11. I also built the git master and could reproduce the problem as well.

It's not entirely clear that this is the same exact bug but the crash backtrace is completely similar

I have a simple reproducer:

$ cat main.cpp 
struct A {
    static constexpr const char *a = "a";
    void foo() { }
};

int main(void) {
    A a;
    a.foo();
}

Compile with g++ 7.1 with C++17 semantics: g++-7 -std=c++17 -g -o main main.cpp

Now run it with gdb:

$ gdb main
GNU gdb (Debian 7.11.1-2~bpo8+1) 7.11.1
(...)
(gdb) b A::foo
Breakpoint 1 at 0x40055e: file main.cpp, line 6.
(gdb) r
Starting program: main 

Breakpoint 1, A::foo (this=0x7fffffffe09f) at main.cpp:6
6	    void foo() { }
(gdb) print *this
Segmentation fault (core dumped)

If I patch the source with the workaround mentioned by Thilo (i.e set the ptr to NULL in the catch block and call cp_print_static_field() only if v is not NULL), it does not crash:
(gdb) print *this
$1 = {static a = <error reading variable: Missing ELF symbol "A::a".>}

If I compile the program above with the default c++ semantics(c++ 14), I get 
(gdb) print *this
$1 = {static a = <optimized out>}

With the current git master (8.0.50.20170801-git), this is the backtrace I get for the gdb crash:

Program terminated with signal SIGSEGV, Segmentation fault.
#0  value_entirely_covered_by_range_vector (value=0x0, ranges=0x90) at value.c:401
401	  if (value->lazy)
(gdb) bt
#0  value_entirely_covered_by_range_vector (value=0x0, ranges=0x90) at value.c:401
#1  0x0000000000563282 in cp_print_static_field (options=<optimized out>, recurse=<optimized out>, stream=<optimized out>, val=<optimized out>, type=<optimized out>) at cp-valprint.c:640
#2  cp_print_value_fields (type=0x0, real_type=0x90, real_type@entry=0xf1cd00, offset=offset@entry=0, address=0, address@entry=140737488347295, stream=0xf194c0, recurse=16998736, recurse@entry=0, val=0xf8fc00, options=0x7fffffffda20, dont_print_vb=0x0, dont_print_statmem=0)
    at cp-valprint.c:335
#3  0x00000000005639ca in cp_print_value_fields_rtti (type=<optimized out>, type@entry=0xf1cd00, valaddr=0xf6a330 "", offset=offset@entry=0, address=140737488347295, stream=0xf194c0, recurse=0, val=0xf8fc00, options=0x7fffffffda20, dont_print_vb=0x0, dont_print_statmem=0)
    at cp-valprint.c:456
#4  0x000000000054bf52 in c_val_print_struct (type=0xf1cd00, valaddr=<optimized out>, embedded_offset=0, address=<optimized out>, stream=<optimized out>, recurse=<optimized out>, original_value=0xf8fc00, options=0x7fffffffda20) at c-valprint.c:412
#5  0x000000000054c46f in c_val_print (type=0xf1cd00, embedded_offset=0, address=0, stream=0xf194c0, recurse=0, original_value=0xf8fc00, options=0x7fffffffda20) at c-valprint.c:530
#6  0x0000000000699270 in val_print (type=0x0, type@entry=0xf1cd00, embedded_offset=0, address=15846656, address@entry=140737488347295, stream=stream@entry=0xf194c0, recurse=32767, recurse@entry=0, val=val@entry=0xf8fc00, options=0x7fffffffdae0, language=0x843b80 <cplus_language_defn>)
    at valprint.c:1109
#7  0x000000000054cc1f in c_value_print (val=0xf8fc00, stream=0xf194c0, options=<optimized out>) at c-valprint.c:702
#8  0x0000000000622218 in print_value (val=val@entry=0xf8fc00, fmtp=fmtp@entry=0x7fffffffdbf0) at ./printcmd.c:1179
#9  0x00000000006222ae in print_command_1 (exp=0xd3e366 "*this", voidprint=1) at ./printcmd.c:1207
#10 0x00000000004999e9 in cmd_func (cmd=<optimized out>, args=<optimized out>, from_tty=<optimized out>) at cli/cli-decode.c:1902
#11 0x0000000000684ce6 in execute_command (p=<optimized out>, p@entry=0xd3e360 "print *this", from_tty=1) at top.c:675
#12 0x00000000005ab7dc in command_handler (command=0xd3e360 "print *this") at event-top.c:590
#13 0x00000000005abad8 in command_line_handler (rl=<optimized out>) at event-top.c:780
#14 0x00000000005aae2c in gdb_rl_callback_handler (rl=0xf6a330 "") at event-top.c:213
#15 0x00000000006c6698 in rl_callback_read_char () at callback.c:220
#16 0x00000000005aad6e in gdb_rl_callback_read_char_wrapper_noexcept () at event-top.c:175
#17 0x00000000005aadd9 in gdb_rl_callback_read_char_wrapper (client_data=<optimized out>) at event-top.c:192
#18 0x00000000005ab300 in stdin_event_handler (error=<optimized out>, client_data=0xd3ebc0) at event-top.c:518
#19 0x00000000005aa215 in gdb_wait_for_event (block=block@entry=1) at event-loop.c:859
#20 0x00000000005aa3d3 in gdb_do_one_event () at event-loop.c:347
#21 0x00000000005aa485 in start_event_loop () at event-loop.c:371
#22 0x00000000005ff408 in captured_command_loop (data=data@entry=0x0) at main.c:325
#23 0x00000000005ac3c3 in catch_errors (func=func@entry=0x5ff3e0 <captured_command_loop(void*)>, func_args=func_args@entry=0x0, errstring=errstring@entry=0x7f0ede "", mask=mask@entry=RETURN_MASK_ALL) at exceptions.c:236
#24 0x0000000000600366 in captured_main (data=0x7fffffffdec0) at main.c:1150
#25 gdb_main (args=args@entry=0x7fffffffdff0) at main.c:1160
#26 0x0000000000411ae5 in main (argc=<optimized out>, argv=<optimized out>) at gdb.c:32
Comment 3 Keith Seitz 2017-08-02 19:55:45 UTC
(In reply to Thilo Voertler from comment #1)
> Any comment would be appreciated

Thank you for chasing this down. I have investigated this a little, and I see this hunk from commit 492d29ea is probably the culprit:

@@ -313,18 +313,21 @@ cp_print_value_fields (struct type *type, struct type *rea
l_type,
                }
              else if (field_is_static (&TYPE_FIELD (type, i)))
                {
-                 volatile struct gdb_exception ex;
                  struct value *v = NULL;
 
-                 TRY_CATCH (ex, RETURN_MASK_ERROR)
+                 TRY
                    {
                      v = value_static_field (type, i);
                    }
 
-                 if (ex.reason < 0)
-                   fprintf_filtered (stream,
-                                     _("<error reading variable: %s>"),
-                                     ex.message);
+                 CATCH (ex, RETURN_MASK_ERROR)
+                   {
+                     fprintf_filtered (stream,
+                                       _("<error reading variable: %s>"),
+                                       ex.message);
+                   }
+                 END_CATCH
+
                  cp_print_static_field (TYPE_FIELD_TYPE (type, i),
                                         v, stream, recurse + 1,
                                         options);

Your patch should fix that. Would you care to submit your (properly formatted) patch (and ChangeLog) to gdb-patches@sourceware.org?

(In reply to Guillaume Morin from comment #2)
> We have started experiencing a similar crash when we switched to g++ 7.1
> with c++17 semantics.  When gdb tries to print a "static constexpr", it
> triggers a "error reading variable: Missing ELF symbol" exception and then
> crashes at the same place as the original reporter. This seems to happen
> with every release at least from gdb 7.11. I also built the git master and
> could reproduce the problem as well.

This appears consistent with this bug, thank you for reporting.

> I have a simple reproducer:
> 

Awesome! Thank you very much for this!

> Now run it with gdb:

I tried your test case (using gcc 7.0-20160916 (experimental) -- the gdb c++ compile branch) and did not reproduce the crash. I will try building something newer. Can you give me the exact compiler version you are using? [g++ -v]

> If I compile the program above with the default c++ semantics(c++ 14), I get 
> (gdb) print *this
> $1 = {static a = <optimized out>}
> 

That appears to be another issue (which I have also investigated). I'm going to open a new bug about this, c++/21892. Let's move the "optimized out" discussion there.
Comment 4 Keith Seitz 2017-08-02 20:18:06 UTC
(In reply to Keith Seitz from comment #3)
> (In reply to Thilo Voertler from comment #1)
> > Any comment would be appreciated
> 
> Thank you for chasing this down. I have investigated this a little, and I
> see this hunk from commit 492d29ea is probably the culprit:

Actually to be pedantic, that's not the problem. The NULL check was already missing by the time that patch was applied. It *does* appear in commit ee86786c, so something between the two erased it.
Comment 5 Guillaume Morin 2017-08-02 23:00:00 UTC
(In reply to Keith Seitz from comment #3)
> I tried your test case (using gcc 7.0-20160916 (experimental) -- the gdb c++
> compile branch) and did not reproduce the crash. I will try building
> something newer. Can you give me the exact compiler version you are using?

This is Debian's gcc 7.1.0-10 (from testing)

Using built-in specs.
COLLECT_GCC=g++-7
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 7.1.0-10' --with-bugurl=file:///usr/share/doc/gcc-7/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-7 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 7.1.0 (Debian 7.1.0-10)

I tested in a Debian testing chroot and reproduced it without any issues. So I believe it should be easy for you to reproduce with a similar version
Comment 6 Guillaume Morin 2017-08-03 19:44:25 UTC
Note: https://sourceware.org/bugzilla/show_bug.cgi?id=20607 is probably the same bug
Comment 7 Jim Muchow 2017-09-14 19:52:47 UTC
This is very interesting; I thought it was only me that experienced this. I have been looking into this issue, off and on (tho' mostly off) for some months. I have found that it can be avoided in our situation, by running "set print static-members off" either by hand or in .gdbinit.

While I agree with Thilo's approach below of testing for a NULL-pointer before calling cp_print_static_field(), it seems to me that this may not actually fix the problem - and perhaps cause another.

I was concerned with the latter case because if gdb was unable to find a variable (in the call to value_static_field()), then perhaps it is better to crash (perhaps using gdb_assert())? This call to value_static_field() after all occurs in a for-loop and so perhaps the problem worsens ignoring by the NULL-pointer? Maybe? I defer to Thilo's experience in this regard; if the fix seems to work with no side effect, great.

I bring up the problem of something else being the real source of the problem because I found in my cases that GDB was trying to reference a variable that I couldn't even find (ie, the cause of the NULL-pointer). In my case there was a C++ template:

template<class BlockConfigurator>

class BlockHolder

{
    ...

    static const uns32 DEBUGLOG_ENUM_LOGALL = 0xFFFFFFFF;
}

During investigation, I discovered that the symbol is not even present in the output of "objdump -t <path>/binary_unstripped". I made the assumption that the symbol was a prime candidate to be optimized out since it is static, const, and with a predefined value. I also assumed that if I used a debug build, that the symbol was more likely to be found. Oddly, it wasn't.

In short, this looks like a situation in which the compiler/linker have conspired, so to speak, against gdb. I'm not really sure there is anything that can be done in this situation except add various conditionals like Thilo's to avoid the problem.

Regards,
Jim Muchow
Comment 8 scott snyder 2018-01-18 03:25:03 UTC
I've started seeing this when printing C++ std::atomic<T*> values.

Here's the reproducer i came up with:

-- x.cc -----------------------------
template<typename _Tp>
struct foo
{
  static constexpr bool is_always_lock_free = true;
};


int main()
{
  foo<int> p;
  return 0;
}
---------------------------------------------------------

Then with 

gcc version 7.2.1 20170915 (Red Hat 7.2.1-2) (GCC) 

we get

$ /usr/bin/gcc -g -o x x.cc -std=c++17
$ ~/tmp/gdb/gdb-8.0.1/gdb/gdb ./x
...
GNU gdb (GDB) 8.0.1
...
Reading symbols from ./x...done.
(gdb) break main
Breakpoint 1 at 0x40048b: file x.cc, line 11.
(gdb) run
Starting program: /home/sss/atlas/dvtest/x 

Breakpoint 1, Python Exception <type 'exceptions.NameError'> Installation error: gdb.execute_unwinders function is missing: 
main () at x.cc:11
11	  return 0;
(gdb) p p
$1 = {
Segmentation fault (core dumped)


The crash is the same as reported earlier in this thread.
Comment 9 Yuriy Yevtukhov 2018-03-09 16:17:54 UTC
Can confirm this bug in GNU gdb (Debian 7.12-6+b1) 7.12.0.20161007-git
when printing std::atomic<> variables. gcc version 7.2.0
Doing "set print static-members off" really helps. Thanks.
Comment 10 weimin.pan 2018-11-16 00:11:05 UTC
This is a duplicate of 20607.
Comment 11 Tom Tromey 2018-11-30 16:57:56 UTC
*** Bug 17685 has been marked as a duplicate of this bug. ***
Comment 12 Tom Tromey 2018-11-30 16:58:34 UTC
I somewhat arbitrarily chose this one as the canonical bug report;
but note that bug 17685 has a test executable which can perhaps
be used to reproduce as well.
Comment 13 Keith Seitz 2018-12-06 16:17:17 UTC
*** Bug 23953 has been marked as a duplicate of this bug. ***
Comment 14 weimin.pan 2019-01-10 00:54:53 UTC
*** Bug 19382 has been marked as a duplicate of this bug. ***
Comment 15 Paul Pluzhnikov 2019-03-24 20:38:50 UTC
Another trivial reproducer from https://stackoverflow.com/questions/55314720/gdb-crashes-when-printing-value-of-atomic-enum

#include <atomic>

enum class foo {ONE, TWO, THREE, FOUR, FIVE, SIX};

int main(int argc, char **argv)
{
  std::atomic<foo> x = foo::FOUR;
  std::atomic<int> y = int(foo::FOUR);
  return 0;
}

g++ -g -std=c++17 t.cc

(gdb) print y -- works fine
(gdb_ print x -- crash in value_entirely_covered_by_range_vector(), using current trunk.

value_entirely_covered_by_range_vector (value=value@entry=0x0, ranges=...) at ../../gdb/value.c:416
416	  if (value->lazy)
Comment 16 Tom Tromey 2019-03-25 04:56:52 UTC
This fixes the atomic crash but I haven't written a test yet.

diff --git a/gdb/cp-valprint.c b/gdb/cp-valprint.c
index 7124da42ec9..8feaae03aac 100644
--- a/gdb/cp-valprint.c
+++ b/gdb/cp-valprint.c
@@ -314,13 +314,14 @@ cp_print_value_fields (struct type *type, struct type *real_type,
 		}
 	      else if (field_is_static (&TYPE_FIELD (type, i)))
 		{
-		  struct value *v = NULL;
-
 		  TRY
 		    {
-		      v = value_static_field (type, i);
-		    }
+		      struct value *v = value_static_field (type, i);
 
+		      cp_print_static_field (TYPE_FIELD_TYPE (type, i),
+					     v, stream, recurse + 1,
+					     options);
+		    }
 		  CATCH (ex, RETURN_MASK_ERROR)
 		    {
 		      fprintf_filtered (stream,
@@ -328,10 +329,6 @@ cp_print_value_fields (struct type *type, struct type *real_type,
 					ex.message);
 		    }
 		  END_CATCH
-
-		  cp_print_static_field (TYPE_FIELD_TYPE (type, i),
-					 v, stream, recurse + 1,
-					 options);
 		}
 	      else if (i == vptr_fieldno && type == vptr_basetype)
 		{
Comment 17 Carlo Wood 2019-05-16 17:25:19 UTC
Before applying Tom's patch:

(gdb) p m_buffer->recording_ringbuffer.m_tail
$3 = {_M_b = {Segmentation fault (core dumped)

After applying Tom's patch:

(gdb) p m_buffer->recording_ringbuffer.m_tail
$1 = {_M_b = {_M_p = 0x0}, static is_always_lock_free = <error reading variable: Missing ELF symbol "std::atomic<evio::RecordingData**>::is_always_lock_free".>}
Comment 18 Tom Tromey 2019-05-17 20:12:22 UTC
FWIW there's also a gcc bug involved
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90526
Comment 19 Sourceware Commits 2019-05-29 15:44:58 UTC
The master branch has been updated by Tom Tromey <tromey@sourceware.org>:

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

commit 4330d61dfb05d77fd925efdca45091f12e3a6266
Author: Tom Tromey <tromey@adacore.com>
Date:   Wed May 29 09:34:50 2019 -0600

    Fix crash in cp_print_value_fields
    
    PR c++/20020 concerns a crash in cp_print_value_fields.  The immediate
    cause is that cp_print_value_fields does not handle the case where
    value_static_field fails.  This is fixed in this patch by calling
    cp_print_static_field from the "try" block.
    
    Digging a bit deeper, the error occurs because GCC does not emit a
    DW_AT_const_value for a static constexpr member appearing in a
    template class.  I've filed a GCC bug for this.
    
    Tested on x86-64 Fedora 29.
    
    gdb/ChangeLog
    2019-05-29  Tom Tromey  <tromey@adacore.com>
    
    	PR c++/20020:
    	* cp-valprint.c (cp_print_value_fields): Call
    	cp_print_static_field inside "try".
    
    gdb/testsuite/ChangeLog
    2019-05-29  Tom Tromey  <tromey@adacore.com>
    
    	PR c++/20020:
    	* gdb.cp/constexpr-field.exp: New file.
    	* gdb.cp/constexpr-field.cc: New file.
Comment 20 Tom Tromey 2019-05-29 15:45:29 UTC
Fixed.
Comment 21 Tom de Vries 2019-06-18 13:51:39 UTC
*** Bug 18929 has been marked as a duplicate of this bug. ***
Comment 22 Sourceware Commits 2019-06-27 13:54:28 UTC
The master branch has been updated by Tom Tromey <tromey@sourceware.org>:

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

commit 3d507ff23b724ecb2b9a5a61cebd0fba275cfbc3
Author: Tom Tromey <tromey@adacore.com>
Date:   Tue Jun 18 09:37:02 2019 -0600

    Fix two buglets in cp_print_value_fields patch
    
    Pedro and Tom both pointed out issues in the cp_print_value_fields
    patch, aka the fix for PR c++/20020.
    
    This patch addresses both issues.  Tested on x86-64 Fedora 29.
    
    gdb/ChangeLog
    2019-06-27  Tom Tromey  <tromey@adacore.com>
    
    	* cp-valprint.c (cp_print_value_fields): Pass opts, not options,
    	to cp_print_static_field.
    
    gdb/testsuite/ChangeLog
    2019-06-27  Tom Tromey  <tromey@adacore.com>
    
    	* gdb.cp/constexpr-field.exp: Use setup_xfail.
Comment 23 Tom Tromey 2019-06-28 12:59:14 UTC
*** Bug 24745 has been marked as a duplicate of this bug. ***
Comment 24 Tom Tromey 2019-08-01 12:42:12 UTC
*** Bug 24864 has been marked as a duplicate of this bug. ***
Comment 25 Sourceware Commits 2019-08-03 07:43:09 UTC
The gdb-8.3-branch branch has been updated by Tom de Vries <vries@sourceware.org>:

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

commit 98c90f80283bbdf7df140041e3b784bfcb3b1d39
Author: Tom Tromey <tromey@adacore.com>
Date:   Sat Aug 3 09:42:28 2019 +0200

    Fix crash in cp_print_value_fields
    
    [ Backport of master commit 4330d61dfb. ]
    
    PR c++/20020 concerns a crash in cp_print_value_fields.  The immediate
    cause is that cp_print_value_fields does not handle the case where
    value_static_field fails.  This is fixed in this patch by calling
    cp_print_static_field from the "try" block.
    
    Digging a bit deeper, the error occurs because GCC does not emit a
    DW_AT_const_value for a static constexpr member appearing in a
    template class.  I've filed a GCC bug for this.
    
    Tested on x86-64 Fedora 29.
    
    gdb/ChangeLog
    2019-05-29  Tom Tromey  <tromey@adacore.com>
    
    	PR c++/20020:
    	* cp-valprint.c (cp_print_value_fields): Call
    	cp_print_static_field inside "try".
    
    gdb/testsuite/ChangeLog
    2019-05-29  Tom Tromey  <tromey@adacore.com>
    
    	PR c++/20020:
    	* gdb.cp/constexpr-field.exp: New file.
    	* gdb.cp/constexpr-field.cc: New file.
Comment 26 Sourceware Commits 2019-08-03 07:43:14 UTC
The gdb-8.3-branch branch has been updated by Tom de Vries <vries@sourceware.org>:

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

commit 15522b80c90063b01a16de98e460dfa52054fba6
Author: Tom Tromey <tromey@adacore.com>
Date:   Sat Aug 3 09:42:28 2019 +0200

    Fix buglet in cp_print_value_fields patch
    
    [ Backport of master commit 3d507ff23b. ]
    
    Pedro pointed out an issue in the cp_print_value_fields
    patch, aka the fix for PR c++/20020.
    
    This patch addresses the issue.  Tested on x86-64 Fedora 29.
    
    gdb/testsuite/ChangeLog
    2019-06-27  Tom Tromey  <tromey@adacore.com>
    
    	* gdb.cp/constexpr-field.exp: Use setup_xfail.
Comment 27 Joel Brobecker 2019-09-16 23:45:58 UTC
switching the milestone to 8.3.1 since the patch was backported.
Comment 28 Sourceware Commits 2019-09-18 20:54:00 UTC
The gdb-8.3-branch branch has been updated by Tom de Vries <vries@sourceware.org>:

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

commit 59047affb0a95c7b76528b91bb378c7117c580ac
Author: Tom de Vries <tdevries@suse.de>
Date:   Wed Sep 18 22:53:21 2019 +0200

    Update ChangeLog entry of commit 98c90f8028 and mention PR c++/20020
Comment 29 Sourceware Commits 2019-10-13 13:10:05 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=d039f01465b37026e538b06ff792aadc4b19bf24

commit d039f01465b37026e538b06ff792aadc4b19bf24
Author: Tom de Vries <tdevries@suse.de>
Date:   Sun Oct 13 15:09:09 2019 +0200

    Mention PR c++/20020 in ChangeLog entry
    
    [ Port of gdb-8.3-branch commit 59047affb0a "Update ChangeLog entry of commit
    98c90f8028 and mention PR c++/20020". ]
Comment 30 Hannes Domani 2020-04-07 23:51:55 UTC
*** Bug 24379 has been marked as a duplicate of this bug. ***
Comment 31 Hannes Domani 2020-04-08 12:16:38 UTC
*** Bug 24865 has been marked as a duplicate of this bug. ***
Comment 33 Mehmet gelisin 2021-09-10 19:36:22 UTC Comment hidden (spam)
Comment 34 Takkelink 2021-11-10 14:16:30 UTC Comment hidden (spam)
Comment 35 Hannes Domani 2024-06-30 17:48:28 UTC
*** Bug 17076 has been marked as a duplicate of this bug. ***