http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49146
Summary: segv from libgcc_s when raising an exception, or
unwinding stack with backtrace
Product: gcc
Version: 4.4.6
Status: UNCONFIRMED
Severity: critical
Priority: P3
Component: target
AssignedTo: [email protected]
ReportedBy: [email protected]
Created attachment 24346
--> http://gcc.gnu.org/bugzilla/attachment.cgi?id=24346
preprocessed file for t_exception.cpp
Unwinding the stack through a frame for a function annotated
with __attribute__((ms_abi)) causes a segv from libgcc_s.
System type: linux x8664, gcc 4.4.6, 4.5.3, and 4.6.0.
This error can be reproduced in two ways.
The first is to throw an exception and there is a function
annotated with __attribute__((ms_abi)) between where it's
thrown and where it's caught.
The other is to call the (libc) function backtrace. On most
contemporary linux x8664 distributions, backtrace calls code
in libgcc_s.so. Note also that in this case the backtrace
shown for f looks wrong (it has too few frames). The segv
occurs in the unwind code in libgcc_s.so.
This is output of gcc -v:
Using built-in specs.
Target: x86_64-unknown-linux-gnu
Configured with: /packages/gcc-4.4.6/src/gcc-4.4.6/configure
--prefix=/packages/gcc-4.4.6/linux-x8664/installation
--with-gmp=/packages/gcc-4.4.6/linux-x8664/installation
--with-mpfr=/packages/gcc-4.4.6/linux-x8664/installation
--with-mpc=/packages/gcc-4.4.6/linux-x8664/installation
--enable-languages=c,c++,fortran
Thread model: posix
gcc version 4.4.6 (GCC)
This is how I built the sample programs:
/packages/gcc-4.4.6/linux-x8664/installation/bin/g++ -save-temps -g
../ms_abi-reproducer/t_exception.cpp -o t_exception
-Wl,-rpath,/packages/gcc-4.4.6/linux-x8664/installation/lib64
/packages/gcc-4.4.6/linux-x8664/installation/bin/gcc -save-temps -g
../ms_abi-reproducer/t_repro.c -o t_repro
-Wl,-rpath,/packages/gcc-4.4.6/linux-x8664/installation/lib64
I submit the preprocessed files as attachments. This is the source
for the two programs:
t_exception.cpp
#include <stdio.h>
struct E {
};
void
f ( int arg )
{
if ( arg > 0 )
{
f ( arg - 1 );
}
else
{
throw E ();
}
} /* f */
int
__attribute__((ms_abi))
f_ms_abi ( int arg )
{
if ( arg > 0 )
{
f_ms_abi ( arg - 1 );
}
else
{
throw E ();
}
} /* f_ms_abi */
int
main ( int argc, char *argv [] )
{
printf ( "calling f\n" );
try
{
f ( 6 );
}
catch ( ... )
{
printf ( "caught exception thrown by f\n" );
}
printf ( "calling f_ms_abi\n" );
try
{
f_ms_abi ( 6 );
}
catch ( ... )
{
printf ( "caught exception thrown by f_ms_abi\n" );
}
return 0;
} /* main */
t_repro.c:
#include <stdio.h>
#include <execinfo.h>
void
do_backtrace (void)
{
void *pcs [ 64 ];
int max_pcs = sizeof ( pcs ) / sizeof ( pcs [ 0 ] );
int num_pcs = backtrace ( pcs, max_pcs );
int i;
for ( i = 0; i < num_pcs; i ++ )
printf ( " %2d: %p\n", i, pcs [ i ] );
} /* do_backtrace */
void
f ( int arg )
{
if ( arg > 0 )
{
f ( arg - 1 );
}
else
{
do_backtrace ();
}
} /* f */
int
__attribute__((ms_abi))
f_ms_abi ( int arg )
{
if ( arg > 0 )
{
f_ms_abi ( arg - 1 );
}
else
{
do_backtrace ();
}
} /* f_ms_abi */
int
main ( int argc, char *argv [] )
{
printf ( "calling f\n" );
f ( 6 );
printf ( "calling f_ms_abi\n" );
f_ms_abi ( 6 );
return 0;
} /* main */