I've isolated where the crash occurs. Within __cxa_type_match(...) the exception routines attempt to determine the type_info of the thrown exception. In my simple test application, this is nothing more than a std::exception. This type_info object lives in the .dynsym section of the executable, and shows up in gdb as the following:
(gdb) x /2 0xd490
0xd490 <_ZTISt9exception (typeinfo for std::exception)>: 0x00000000 0x00000000
(That's a null pointer to the vtable and typename, respectively). Conversely, the libsupc--.so library does have correct the correct type information: by copying these values manually, I was able to successfully throw and catch the exception.
This problem seems to be due to Android's default use of the -Bsymbolic linker option [1]. By removing this option from the affected libraries, it indeed changes the linking of the type_info objects. The resulting symbols all have the relocation type R_ARM_REL32. Unfortunately, neither the runtime or prelinker have support for this symbol type. I added the following code to the dynamic linker:
@@ -1236,6 +1236,13 @@ static int reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count)
break;
case R_ARM_NONE:
break;
+ case R_ARM_REL32:
+ COUNT_RELOC(RELOC_RELATIVE);
+ MARK(rel->r_offset);
+ TRACE_TYPE(RELO, "%5d RELO REL32 %08x <- %08x - %08x %s\n", pid,
+ reloc, sym_addr, rel->r_offset, sym_name);
+ *((unsigned*)reloc) += sym_addr - rel->r_offset;
+ break;
This causes the type_info objects to link correctly, however the vtables still contain nulls, so the code isn't yet fully functional.
--nathan
[1]
http://www.gnu.org/software/gcc/faq.html#dso