http://sourceware.org/ml/gdb-patches/2010-09/msg00440.html Subject: [patch] Fix infinite loop crash on self-referencing class Hi, class C { static C s; }; is a problem for GDB as it references itself and it can crash. Downstream Bug: https://bugzilla.redhat.com/show_bug.cgi?id=627432 #3 0x00000000005b2cc5 in gnuv3_pass_by_reference (type=0x1044d3c8) at ../../gdb/gnu-v3-abi.c:840 #4 0x00000000005b2cc5 in gnuv3_pass_by_reference (type=0x1044d3c8) at ../../gdb/gnu-v3-abi.c:840 [...] No regressions on {x86_64,x86_64-m32,i686}-fedora13-linux-gnu. FYI the .cc file is not reproducible on - and only on - Fedora 14 GCC, filed: https://bugzilla.redhat.com/show_bug.cgi?id=637315 I would even check it in in some time. Thanks, Jan gdb/ 2010-09-24 Jan Kratochvil Fix GDB crash on inferior calls with self-referencing classes. * gnu-v3-abi.c (gnuv3_pass_by_reference): Do not call itself on static member fields. gdb/testsuite/ 2010-09-24 Jan Kratochvil Fix GDB crash on inferior calls with self-referencing classes. * gdb.dwarf2/dw2-cp-infcall-ref-static.exp: New file. * gdb.dwarf2/dw2-cp-infcall-ref-static-main.c: New file. * gdb.dwarf2/dw2-cp-infcall-ref-static.S: New file. --- a/gdb/gnu-v3-abi.c +++ b/gdb/gnu-v3-abi.c @@ -835,9 +835,10 @@ gnuv3_pass_by_reference (struct type *type) by reference, so does this class. Similarly for members, which are constructed whenever this class is. We do not need to worry about recursive loops here, since we are only looking at members - of complete class type. */ + of complete class type. Also ignore any static members. */ for (fieldnum = 0; fieldnum < TYPE_NFIELDS (type); fieldnum++) - if (gnuv3_pass_by_reference (TYPE_FIELD_TYPE (type, fieldnum))) + if (TYPE_FIELD_LOC_KIND (type, fieldnum) == FIELD_LOC_KIND_BITPOS + && gnuv3_pass_by_reference (TYPE_FIELD_TYPE (type, fieldnum))) return 1; return 0; --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/dw2-cp-infcall-ref-static-main.c @@ -0,0 +1,51 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2010 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* class C + { + public: + static C s; + }; + C C::s; + C f() + { + return C::s; + } */ + +asm (".globl cu_text_start"); +asm ("cu_text_start:"); + +asm (".globl f_start"); +asm ("f_start:"); + +void +f (void) +{ +} + +asm (".globl f_end"); +asm ("f_end:"); + +int +main (void) +{ + f (); + return 0; +} + +asm (".globl cu_text_end"); +asm ("cu_text_end:"); --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/dw2-cp-infcall-ref-static.S @@ -0,0 +1,115 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2010 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Debug information */ + + .section .debug_info +.Lcu1_begin: + /* CU header */ + .4byte .Lcu1_end - .Lcu1_start /* Length of Compilation Unit */ +.Lcu1_start: + .2byte 2 /* DWARF Version */ + .4byte .Labbrev1_begin /* Offset into abbrev section */ + .byte 4 /* Pointer size */ + + /* CU die */ + .uleb128 1 /* Abbrev: DW_TAG_compile_unit */ + .4byte cu_text_start /* DW_AT_low_pc */ + .4byte cu_text_end /* DW_AT_high_pc */ + .ascii "file1.txt\0" /* DW_AT_name */ + .ascii "GNU C 3.3.3\0" /* DW_AT_producer */ + .byte 4 /* DW_AT_language (DW_LANG_C_plus_plus) */ + +.Ltype_class: + .uleb128 3 /* Abbrev: DW_TAG_class_type */ + .ascii "C\0" /* DW_AT_name */ + + .uleb128 4 /* Abbrev: DW_TAG_member */ + .ascii "s\0" /* DW_AT_name */ + .4byte .Ltype_class-.Lcu1_begin /* DW_AT_type */ + .byte 1 /* DW_AT_declaration */ + .byte 1 /* DW_AT_external */ + + .byte 0 /* End of children of DW_TAG_class_type */ + + .uleb128 5 /* Abbrev: DW_TAG_subprogram */ + .ascii "f\0" /* DW_AT_name */ + .4byte .Ltype_class-.Lcu1_begin /* DW_AT_type */ + .4byte f_start /* DW_AT_low_pc */ + .4byte f_end /* DW_AT_high_pc */ + + .byte 0 /* End of children of CU */ + +.Lcu1_end: + +/* Abbrev table */ + .section .debug_abbrev +.Labbrev1_begin: + .uleb128 1 /* Abbrev code */ + .uleb128 0x11 /* DW_TAG_compile_unit */ + .byte 1 /* has_children */ + .uleb128 0x11 /* DW_AT_low_pc */ + .uleb128 0x1 /* DW_FORM_addr */ + .uleb128 0x12 /* DW_AT_high_pc */ + .uleb128 0x1 /* DW_FORM_addr */ + .uleb128 0x3 /* DW_AT_name */ + .uleb128 0x8 /* DW_FORM_string */ + .uleb128 0x25 /* DW_AT_producer */ + .uleb128 0x8 /* DW_FORM_string */ + .uleb128 0x13 /* DW_AT_language */ + .uleb128 0xb /* DW_FORM_data1 */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + + .uleb128 3 /* Abbrev code */ + .uleb128 0x2 /* DW_TAG_class_type */ + .byte 1 /* has_children */ + .uleb128 0x3 /* DW_AT_name */ + .uleb128 0x8 /* DW_FORM_string */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + + .uleb128 4 /* Abbrev code */ + .uleb128 0xd /* DW_TAG_member */ + .byte 0 /* has_children */ + .uleb128 0x3 /* DW_AT_name */ + .uleb128 0x8 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x3c /* DW_AT_declaration */ + .uleb128 0xc /* DW_FORM_flag */ + .uleb128 0x3f /* DW_AT_external */ + .uleb128 0xc /* DW_FORM_flag */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + + .uleb128 5 /* Abbrev code */ + .uleb128 0x2e /* DW_TAG_subprogram */ + .byte 0 /* has_children */ + .uleb128 0x3 /* DW_AT_name */ + .uleb128 0x8 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x11 /* DW_AT_low_pc */ + .uleb128 0x1 /* DW_FORM_addr */ + .uleb128 0x12 /* DW_AT_high_pc */ + .uleb128 0x1 /* DW_FORM_addr */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/dw2-cp-infcall-ref-static.exp @@ -0,0 +1,49 @@ +# Copyright 2010 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Check that GDB can call C++ functions whose parameters or return values have +# type containing a static member of the same type. + +# Still no C++ compiler is used. +if { [skip_cplus_tests] } { continue } + +# This test can only be run on targets which support DWARF-2 and use gas. +# For now pick a sampling of likely targets. +if {![istarget *-*-linux*] + && ![istarget *-*-gnu*] + && ![istarget *-*-elf*] + && ![istarget *-*-openbsd*] + && ![istarget arm-*-eabi*] + && ![istarget powerpc-*-eabi*]} { + return 0 +} + +set testfile "dw2-cp-infcall-ref-static" +if { [prepare_for_testing ${testfile}.exp ${testfile} [list ${testfile}-main.c ${testfile}.S] {}] } { + return -1 +} + +if ![runto_main] then { + return -1 +} + +# main is not provided by DWARF. +gdb_test_no_output "set language c++" + +# There are no mangled names in DWARF to suggest the v3 ABI. +gdb_test_no_output "set cp-abi gnu-v3" + +# GDB could crash. There is no DW_AT_location so it is . +gdb_test "p f()" { = {static s = }}