* SIGSEGV in gdb 6.4 debugging gcc 2.95 stabs, with possible fix
@ 2006-05-05 19:41 Simon Baldwin
2006-05-05 21:43 ` Jim Blandy
0 siblings, 1 reply; 2+ messages in thread
From: Simon Baldwin @ 2006-05-05 19:41 UTC (permalink / raw)
To: gdb
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.
__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: SIGSEGV in gdb 6.4 debugging gcc 2.95 stabs, with possible fix
2006-05-05 19:41 SIGSEGV in gdb 6.4 debugging gcc 2.95 stabs, with possible fix Simon Baldwin
@ 2006-05-05 21:43 ` Jim Blandy
0 siblings, 0 replies; 2+ messages in thread
From: Jim Blandy @ 2006-05-05 21:43 UTC (permalink / raw)
To: Simon Baldwin; +Cc: gdb
Simon Baldwin <simon_baldwin@yahoo.com> 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;
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2006-05-05 21:43 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-05-05 19:41 SIGSEGV in gdb 6.4 debugging gcc 2.95 stabs, with possible fix Simon Baldwin
2006-05-05 21:43 ` Jim Blandy
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox