Marcel Smit
unread,Mar 24, 2011, 8:46:40 AM3/24/11Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to android-ndk
Hi all,
I encounter a segmentation fault during a dynamic_cast in combination
with the use of shared libraries. There's no problem when everything
is
build statically.
Specifically the problem occurs when having a shared library which
uses
rtti/exceptions and which links (statically as that is the only option
currently) libsup++ that is linked to an executable which also uses
rtti/exceptions.
Inspection shows this executable does not statically link the libsup++
code but rather dynamically links the libsup++ code linked into the
shared lib.
The crash occurs on a dynamic_cast<> in the code of the main
executable.
dynamic_cast<>'s in the shared library code do not crash.
Version information:
Android emulator version: Android 9
NDK version: r5b
Toolchain version : 9
Below the reproducer code and gcc command lines with which I've
(cross)built this reproducer.
After that, the output of the reproducer and logcat are shown.
Since the same construction is used in our project code very often, it
is a pretty big issue for us.
Hopefully somebody is able to reproduce this on his own system and can
confirm this is an issue.
Thanks for your help.
Marcel Smit
I've created the following reproducer code:
Library (cast_lib.cpp) :
/**
* Reproducer of the dynamic_cast crash on Android 9, using the NDK
r5b
* toolchain
*/
#include <stdexcept>
namespace
{
struct Base
{
virtual ~Base()
{}
};
struct Derived : public Base
{
int value;
};
struct Another : public Base
{
int x;
int y;
};
}
void test()
{
::printf ("***** starting test in shared lib\n");
::printf (">>> dynamic_cast\n");
Derived d;
d.value = 24;
Base * b1 = &d;
Derived * d1 = dynamic_cast<Derived*>(b1);
if (d1 == 0)
{
::printf ("dynamic_cast returns null, expected value\n");
}
::printf ("<<< dynamic_cast\n");
::printf (">>> dynamic_cast: value check\n");
d1->value = 42;
if (d.value != 42)
{
::printf ("Wrong value after dynamic_cast, expected %d, got %d
\n", 42, d.value);
}
::printf ("<<< dynamic_cast: value check\n");
::printf (">>> dynamic_cast: invalid cast\n");
Another a;
Base * b2 = &a;
Derived * d2 = dynamic_cast<Derived*>(b2);
if (d2 != 0)
{
::printf ("dynamic_cast should return nill\n");
}
::printf ("<<< dynamic_cast: invalid cast\n");
::printf ("***** finished test in shared lib\n");
}
/*************************************************************/
Main (cast.cpp):
/**
* Reproducer of the dynamic_cast crash on Android 9, using the NDK r5
* toolchain
*/
#include <stdexcept>
namespace
{
struct Base2
{
virtual ~Base2()
{}
};
struct Derived2 : public Base2
{
int value;
};
}
extern void test();
int main(int , char **)
{
int status = 0;
test ();
::printf ("***** starting test in main\n");
// Make sure dynamic cast through pointers work ...
Derived2 d;
d.value = 24;
Base2 * b1 = &d;
Derived2 * d1 = dynamic_cast<Derived2*>(b1);
if (d1 == 0)
{
status = 1;
::printf ("dynamic_cast returns null, expected value\n");
}
::printf ("***** finished test in main\n");
return status;
}
/*************************************************************/
The following commands are used to build the library:
arm-linux-androideabi-g++ -W -Wall -Wpointer-arith -ggdb
-Wa,--noexecstack -O0 -pipe -D_REENTRANT -D_GNU_SOURCE
-ffunction-sections -funwind-tables -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__
-D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -DANDROID -Wno-psabi -
march=armv5te
-mtune=xscale -msoft-float -mthumb -Os -fomit-frame-pointer
-fno-strict-aliasing -finline-limit=64 -fexceptions -frtti -I.. -c -
fPIC
-o cast_lib.o cast_lib.cpp
arm-linux-androideabi-g++ -Wl,-O3 -D_REENTRANT -D_GNU_SOURCE
-ffunction-sections -funwind-tables -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__
-D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -DANDROID -Wno-psabi -
march=armv5te
-mtune=xscale -msoft-float -mthumb -Os -fomit-frame-pointer
-fno-strict-aliasing -finline-limit=64 -fexceptions -frtti -I.. -
shared
-Wl,-h -Wl,libcast.so -o libcast.so cast_lib.o -Wl,-rpath-link,`pwd`
-Wl,-E -lsupc++ -lstdc++ -Wl,--gc-sections -Wl,-z,nocopyreloc
-Wl,--no-undefined -Wl,-z,noexecstack -L../lib -L. -L../lib -ldl
The following command is used to build the program:
arm-linux-androideabi-g++ -W -Wall -Wpointer-arith -ggdb
-Wa,--noexecstack -O0 -frtti -pipe -D_REENTRANT -D_GNU_SOURCE -fpic
-ffunction-sections -funwind-tables -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__
-D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -DANDROID -Wno-psabi -
march=armv5te
-mtune=xscale -msoft-float -mthumb -Os -fomit-frame-pointer
-fno-strict-aliasing -finline-limit=64 -fexceptions -I.. -fPIC -L.
-lcast -Wl,-E -lsupc++ -lstdc++ -Wl,--gc-sections -Wl,-z,nocopyreloc
-Wl,--no-undefined -Wl,-z,noexecstack -ldl -o cast cast.cpp
When running on an emulator, the following output is generated:
[xxxxx@fc14androidr9 platform-tools]$ ./adb shell
# logcat -c
# LD_LIBRARY_PATH=/data/tests;export LD_LIBRARY_PATH
# cd /data/tests
# ./cast
***** starting test in shared lib
>>> dynamic_cast
<<< dynamic_cast
>>> dynamic_cast: value check
<<< dynamic_cast: value check
>>> dynamic_cast: invalid cast
<<< dynamic_cast: invalid cast
***** finished test in shared lib
***** starting test in main
[1] + Stopped (signal) ./cast
#
[1] Segmentation fault ./cast
# logcat
I/DEBUG ( 30): *** *** *** *** *** *** *** *** *** *** *** *** ***
*** *** ***
I/DEBUG ( 30): Build fingerprint: 'generic/sdk/generic:2.3.1/
GSI11/93351:eng/test-keys'
I/DEBUG ( 30): pid: 299, tid: 299 >>> ./cast <<<
I/DEBUG ( 30): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault
addr 00000000
I/DEBUG ( 30): r0 000097b0 r1 00000000 r2 00000006 r3 000097b0
I/DEBUG ( 30): r4 00000000 r5 be8f0c84 r6 be8f0cb0 r7 000097b0
I/DEBUG ( 30): r8 00000000 r9 00000000 10 00000000 fp 00000000
I/DEBUG ( 30): ip 000098c8 sp be8f0c68 lr 80005ca7 pc
00000000 cpsr 00000010
I/DEBUG ( 30): #00 pc 00000000
I/DEBUG ( 30): #01 pc 00005ca4 /data/tests/libcast.so
I/DEBUG ( 30):
I/DEBUG ( 30): code around pc:
I/DEBUG ( 30):
I/DEBUG ( 30): code around lr:
I/DEBUG ( 30): 80005c84 60ab606b 930760eb 612b2310 91056803
I/DEBUG ( 30): 80005c94 91019200 95039602 69dc2206 1c3b9904
I/DEBUG ( 30): 80005ca4 9a0747a0 d02e2a00 200668eb 40011c19
I/DEBUG ( 30): 80005cb4 d0282906 686c68a9 4020400c d0222806
I/DEBUG ( 30): 80005cc4 40012005 d01d2904 d1142b00 2b009b04
I/DEBUG ( 30):
I/DEBUG ( 30): stack:
I/DEBUG ( 30): be8f0c28 afd42664 /system/lib/libc.so
I/DEBUG ( 30): be8f0c2c 0000a008 [heap]
I/DEBUG ( 30): be8f0c30 0000001c
I/DEBUG ( 30): be8f0c34 afd18407 /system/lib/libc.so
I/DEBUG ( 30): be8f0c38 afd42664 /system/lib/libc.so
I/DEBUG ( 30): be8f0c3c 00000001
I/DEBUG ( 30): be8f0c40 be8f0c94
I/DEBUG ( 30): be8f0c44 afd18453 /system/lib/libc.so
I/DEBUG ( 30): be8f0c48 afd42664 /system/lib/libc.so
I/DEBUG ( 30): be8f0c4c afd19321 /system/lib/libc.so
I/DEBUG ( 30): be8f0c50 00000001
I/DEBUG ( 30): be8f0c54 00000000
I/DEBUG ( 30): be8f0c58 be8f0c94
I/DEBUG ( 30): be8f0c5c 00000001
I/DEBUG ( 30): be8f0c60 df002777
I/DEBUG ( 30): be8f0c64 e3a070ad
I/DEBUG ( 30): #01 be8f0c68 be8f0cb0
I/DEBUG ( 30): be8f0c6c 000097a8 /data/tests/cast
I/DEBUG ( 30): be8f0c70 be8f0cb0
I/DEBUG ( 30): be8f0c74 be8f0c84
I/DEBUG ( 30): be8f0c78 00000000
I/DEBUG ( 30): be8f0c7c 000097a8 /data/tests/cast
I/DEBUG ( 30): be8f0c80 00000001
I/DEBUG ( 30): be8f0c84 00000000
I/DEBUG ( 30): be8f0c88 00000000
I/DEBUG ( 30): be8f0c8c 00000000
I/DEBUG ( 30): be8f0c90 00000000
I/DEBUG ( 30): be8f0c94 00000010
I/DEBUG ( 30): be8f0c98 00000002
I/DEBUG ( 30): be8f0c9c 00000000
I/DEBUG ( 30): be8f0ca0 00000001
I/DEBUG ( 30): be8f0ca4 afd41504 /system/lib/libc.so
I/DEBUG ( 30): be8f0ca8 be8f0cec
I/DEBUG ( 30): be8f0cac 00008637 /data/tests/cast
I/BootReceiver( 59): Copying /data/tombstones/tombstone_01 to
DropBox (SYSTEM_TOMBSTONE)
[xxxx@fc14androidr9 plain_c]$ arm-linux-androideabi-addr2line -e ./
libcast.so 00005ca4
/tmp/ndk/src/build/../gcc/gcc-4.4.3/libstdc++-v3/libsupc++/dyncast.cc:
47