From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5734 invoked by alias); 5 May 2006 21:43:40 -0000 Received: (qmail 5722 invoked by uid 22791); 5 May 2006 21:43:40 -0000 X-Spam-Check-By: sourceware.org Received: from intranet.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.6) by sourceware.org (qpsmtpd/0.31) with ESMTP; Fri, 05 May 2006 21:43:37 +0000 Received: (qmail 16074 invoked from network); 5 May 2006 21:43:35 -0000 Received: from unknown (HELO localhost) (jimb@127.0.0.2) by mail.codesourcery.com with ESMTPA; 5 May 2006 21:43:35 -0000 To: Simon Baldwin Cc: gdb@sourceware.org Subject: Re: SIGSEGV in gdb 6.4 debugging gcc 2.95 stabs, with possible fix References: <20060505194143.28509.qmail@web34615.mail.mud.yahoo.com> From: Jim Blandy Date: Fri, 05 May 2006 21:43:00 -0000 In-Reply-To: <20060505194143.28509.qmail@web34615.mail.mud.yahoo.com> (Simon Baldwin's message of "Fri, 5 May 2006 12:41:43 -0700 (PDT)") Message-ID: User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-IsSubscribed: yes Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org X-SW-Source: 2006-05/txt/msg00039.txt.bz2 Simon Baldwin writes: > gdb 6.4 SIGSEGVs with g++ 2.95.3 built binaries that happen to have a > particular layout of virtual functions in a given class. For example: > > $ cat vf.cc > class Foo { > public: > virtual ~Foo() {} > Foo() {} > }; > > int main() { > Foo f; > } > > $ gcc-2.95.3-glibc-2.2.2 -x c++ -pedantic -g -o vf vf.cc > > $ gdb-6.4/gdb/gdb /tmp/vf > GNU gdb 6.4 > Copyright 2005 Free Software Foundation, Inc. > GDB is free software, covered by the GNU General Public License, and you > are > welcome to change it and/or distribute copies of it under certain > conditions. > Type "show copying" to see the conditions. > There is absolutely no warranty for GDB. Type "show warranty" for details. > This GDB was configured as "i686-pc-linux-gnu"...Using host libthread_db > library "/lib/libthread_db.so.1". > > (gdb) break Foo::Foo > Segmentation fault > > Running gdb within gdb reveals > > Program received signal SIGSEGV, Segmentation fault. > gnuv2_is_destructor_name (name=0x0) at gnu-v2-abi.c:45 > 45 if ((name[0] == '_' && is_cplus_marker (name[1]) && name[2] == > '_') > > The cause turns out to be an unset element in the field lists passed to > add_matching_methods() in linespec.c. The actual unset element occurs > because of mismatch can occur between the sublist length and the value of > 'length' at lines 2549 and later in stabsread.c. Here, an array of 'length' > elements is allocated (and zeroed), but fewer elements are then copied in by > the loop at line 2554. > > The fix, while a long way from the problem symptom, is, I believe: > > *** /local/gdb/gdb-6.4/gdb/stabsread.c 2005-07-04 06:29:12.000000000 -0700 > --- ./stabsread.c 2006-05-05 12:22:02.000000000 -0700 > *************** > *** 2492,2497 **** > --- 2492,2498 ---- > { > if (!is_destructor_name (tmp_sublist->fn_field.physname)) > { > + last_sublist = tmp_sublist; > tmp_sublist = tmp_sublist->next; > continue; > } > > Is this a known problem? If not, does the above look like a good candidate > patch? Thanks for tracking this down! If I'm understanding right, the problem is that the 'if' at the top of the list doesn't update last_sublist, so when it comes time to splice out a destructor that follows a non-destructor, we don't properly update the preceding node's 'next' pointer, and the list gets corrupted. Is that right? Isn't there a further bug, though, in that when we do remove a destructor from the list, we set last_sublist to point to the node we just removed? If the next node is a destructor, too, then we'll update the wrong link again. (Although, why a list would have more than one destructor, I don't know.) How does the following look to you? *** stabsread.c 17 Jan 2006 14:12:08 -0800 1.84 --- stabsread.c 05 May 2006 14:41:59 -0700 *************** *** 2492,2511 **** i = 0; while (tmp_sublist != NULL) { ! if (!is_destructor_name (tmp_sublist->fn_field.physname)) ! { ! tmp_sublist = tmp_sublist->next; ! continue; ! } ! ! destr_fnlist->fn_fieldlist.fn_fields[i++] ! = tmp_sublist->fn_field; ! if (last_sublist) ! last_sublist->next = tmp_sublist->next; ! else ! sublist = tmp_sublist->next; ! last_sublist = tmp_sublist; ! tmp_sublist = tmp_sublist->next; } destr_fnlist->fn_fieldlist.length = has_destructor; --- 2492,2510 ---- i = 0; while (tmp_sublist != NULL) { ! if (is_destructor_name (tmp_sublist->fn_field.physname)) ! { ! destr_fnlist->fn_fieldlist.fn_fields[i++] ! = tmp_sublist->fn_field; ! if (last_sublist) ! last_sublist->next = tmp_sublist->next; ! else ! sublist = tmp_sublist->next; ! } ! else ! last_sublist = tmp_sublist; ! ! tmp_sublist = tmp_sublist->next; } destr_fnlist->fn_fieldlist.length = has_destructor;