<div dir="ltr"><div>Background:</div>Android has an malloc debug function which described in <a href="https://android.googlesource.com/platform/bionic/+/master/libc/malloc_debug/">https://android.googlesource.com/platform/bionic/+/master/libc/malloc_debug/</a>. When it is enabled, it use libunwind _Unwind_Backtrace to record malloc stacktrace and can analyze memory problems such as memory leaks.<div>Condition 1:<br><div>It works from Android 5.0 with libunwind(still in libcxxabi) commit <a href="https://llvm.org/viewvc/llvm-project?view=revision&revision=216730">https://llvm.org/viewvc/llvm-project?view=revision&revision=216730</a>.</div><div>This commit avoids call personality function likes __gxx_personality_v0 but with &__gxx_personality_v0 which means only in static build it can continue unwinding.</div></div><div><br></div><div>Condition 2:</div><div>Android 6.0 pick up libunwind(still in libcxxabi) commit <a href="https://llvm.org/viewvc/llvm-project?view=revision&revision=226822">https://llvm.org/viewvc/llvm-project?view=revision&revision=226822</a>.</div><div>This commit try to fix Condition 1 by call personality function in Generic Model.</div><div>And it leads to the problem I will describe later.</div><div><br></div><div>Condition 3:</div><div>Android 7.0 comes with libunwind move out from libcxxabi and pick up libunwind commit <a href="https://llvm.org/viewvc/llvm-project?view=revision&revision=238560">https://llvm.org/viewvc/llvm-project?view=revision&revision=238560</a>.</div><div>This commit do further more and only calls personality function in _Unwind_Backtrace. To use this commit, libcxxabi should pick up commit <a href="https://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/cxa_personality.cpp?r1=238561&r2=238560&pathrev=238561">https://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/cxa_personality.cpp?r1=238561&r2=238560&pathrev=238561</a>.</div><div><br></div><div>Problem in ARM EHABI likes armv7a:</div><div>When using malloc debug in Android, it means the application loads libc_malloc_debug first, and it is compiled with libunwind(llvm). And my application still use gnustl static or shared which means libgcc_s.a is used for user application.</div><div>And when the application calls malloc, it will go into libc_malloc_debug and call libunwind _Unwind_Backtrace() and _Unwind_Backtrace() will call personality function. In Android 6.0, it calls libgcc_s personality function in <a href="https://android.googlesource.com/toolchain/gcc/+/ndk-r15-release/gcc-4.9/libstdc++-v3/libsupc++/eh_personality.cc">https://android.googlesource.com/toolchain/gcc/+/ndk-r15-release/gcc-4.9/libstdc++-v3/libsupc++/eh_personality.cc</a>. And it dies with the backtrace as follows:</div><div><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div>02-25 21:42:28.269 F/DEBUG   (  285): pid: 12453, tid: 12453, name: mo.helloandroid  >>> com.jean.demo.helloandroid <<<</div></div><div><div>02-25 21:42:28.269 F/DEBUG   (  285): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0</div></div><div><div>02-25 21:42:28.289 F/DEBUG   (  285):     r0 00000001  r1 00004080  r2 00000000  r3 00000008</div></div><div><div>02-25 21:42:28.289 F/DEBUG   (  285):     r4 00004080  r5 bea56a28  r6 00000080  r7 00000000</div></div><div><div>02-25 21:42:28.289 F/DEBUG   (  285):     r8 bea564e4  r9 bea565a8  sl 80000000  fp 00000005</div></div><div><div>02-25 21:42:28.289 F/DEBUG   (  285):     ip b39c61b8  sp bea563b8  lr b39d6955  pc b39d64bc  cpsr 240d1c30</div></div><div><div>02-25 21:42:28.300 F/DEBUG   (  285):</div></div><div><div>02-25 21:42:28.300 F/DEBUG   (  285): backtrace:</div></div><div><div><br></div></div><div><div>02-25 21:42:28.300 F/DEBUG   (  285):     #00 pc 000144bc  /data/app/com.jean.demo.helloandroid-1/lib/arm/libnative-lib.so (_Unwind_VRS_Pop+47)</div></div><div><div>/Volumes/Android/buildbot/src/android/gcc/toolchain/build/../gcc/gcc-4.9/libgcc/config/arm/unwind-arm.c:240</div></div><div><div><br></div></div><div><div>02-25 21:42:28.300 F/DEBUG   (  285):     #01 pc 00014951  /data/app/com.jean.demo.helloandroid-1/lib/arm/libnative-lib.so (__gnu_unwind_execute+162)</div></div><div><div>/Volumes/Android/buildbot/src/android/gcc/toolchain/build/../gcc/gcc-4.9/libgcc/config/arm/pr-support.c:153</div></div><div><div><br></div></div><div><div>02-25 21:42:28.300 F/DEBUG   (  285):     #02 pc 00014b45  /data/app/com.jean.demo.helloandroid-1/lib/arm/libnative-lib.so (__gnu_unwind_frame+32)</div></div><div><div>/Volumes/Android/buildbot/src/android/gcc/toolchain/build/../gcc/gcc-4.9/libgcc/config/arm/pr-support.c:331</div></div><div><div><br></div></div><div><div>02-25 21:42:28.300 F/DEBUG   (  285):     #03 pc 00004599  /data/app/com.jean.demo.helloandroid-1/lib/arm/libnative-lib.so (__gxx_personality_v0+336)</div></div><div><div>/Volumes/Android/buildbot/src/android/ndk-r15-release/toolchain/gcc/gcc-4.9/libstdc++-v3/libsupc++/eh_personality.cc:386</div></div><div><div><br></div></div><div><div>02-25 21:42:28.301 F/DEBUG   (  285):     #04 pc 00008517  /system/lib/libc_malloc_debug_leak.so (_Unwind_Backtrace+130)</div></div><div><div>02-25 21:42:28.301 F/DEBUG   (  285):     #05 pc 00006003  /system/lib/libc_malloc_debug_leak.so (get_backtrace(unsigned int*, unsigned int)+34)</div></div><div><div>02-25 21:42:28.301 F/DEBUG   (  285):     #06 pc 00006a7d  /system/lib/libc_malloc_debug_leak.so (leak_malloc+84)</div></div><div><div>02-25 21:42:28.301 F/DEBUG   (  285):     #07 pc 00007911  /data/app/com.jean.demo.helloandroid-1/lib/arm/libnative-lib.so (operator new(unsigned int)+12)</div></div><div><div>02-25 21:42:28.301 F/DEBUG   (  285):     #08 pc 00006eb1  /data/app/com.jean.demo.helloandroid-1/lib/arm/libnative-lib.so (char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag)+144)</div></div><div><div>02-25 21:42:28.302 F/DEBUG   (  285):     #09 pc 000071e3  /data/app/com.jean.demo.helloandroid-1/lib/arm/libnative-lib.so (std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)+30)</div></div><div><div>02-25 21:42:28.302 F/DEBUG   (  285):     #10 pc 000041f3  /data/app/com.jean.demo.helloandroid-1/lib/arm/libnative-lib.so (Java_com_jean_demo_helloandroid_MainActivity_stringFromJNI+58)</div></div><div><div>02-25 21:42:28.302 F/DEBUG   (  285):     #11 pc 008629e9  /data/app/com.jean.demo.helloandroid-1/oat/arm/base.odex (offset 0x432000) (java.lang.String com.jean.demo.helloandroid.MainActivity.stringFromJNI()+76)</div></div><div><div>02-25 21:42:28.302 F/DEBUG   (  285):     #12 pc 008626f9  /data/app/com.jean.demo.helloandroid-1/oat/arm/base.odex (offset 0x432000) (void com.jean.demo.helloandroid.MainActivity.onCreate(android.os.Bundle)+444)</div></div></blockquote><div><br></div><div>After some investigate to this problem, I find there are some problems here.</div><div>(1) <b>Is it designed to mix libunwind(llvm) with libgcc_s personality routine?</b> libgcc_s has compatible _Unwind_Control_Block with libunwind but has incompatible _Unwind_Context with libunwind.</div><div>In gcc, _Unwind_Context is</div><div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">struct core_regs<br>{<br>  _uw r[16];<br>};<br>/* We use normal integer types here to avoid the compiler generating<br>   coprocessor instructions.  */<br>struct vfp_regs<br>{<br>  _uw64 d[16];<br>  _uw pad;<br>};<br>struct vfpv3_regs<br>{<br>  /* Always populated via VSTM, so no need for the "pad" field from<br>     vfp_regs (which is used to store the format word for FSTMX).  */<br>  _uw64 d[16];<br>};<br>struct wmmxd_regs<br>{<br>  _uw64 wd[16];<br>};<br>struct wmmxc_regs<br>{<br>  _uw wc[4];<br>};<br>typedef struct<br>{<br>  /* The first fields must be the same as a phase2_vrs.  */<br>  _uw demand_save_flags;<br>  struct core_regs core;<br>  _uw prev_sp; /* Only valid during forced unwinding.  */<br>  struct vfp_regs vfp;<br>  struct vfpv3_regs vfp_regs_16_to_31;<br>  struct wmmxd_regs wmmxd;<br>  struct wmmxc_regs wmmxc;<br>} phase1_vrs;</blockquote></div><div>But in libunwind, it is a class with vptr UnwindCursor<LocalAddressSpace, Registers_arm>.</div><div><br></div><div>In <a href="https://android.googlesource.com/toolchain/gcc/+/ndk-r15-release/gcc-4.9/libgcc/config/arm/pr-support.c">https://android.googlesource.com/toolchain/gcc/+/ndk-r15-release/gcc-4.9/libgcc/config/arm/pr-support.c</a>, it also calls</div><div>_Unwind_VRS_Set (context, _UVRSC_CORE, R_PC, _UVRSD_UINT32,</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                  </span>       &reg);</div><div>to store context but what's the context here?</div><div><br></div><div>(2) Since I have no way because Android use libunwind and our application should still use gnustl for a while. It means the mix will long exists.</div><div>(3) Actually in Condition 1, it sounds it does not call personality function for Generic Model, but since it calls _Unwind_VRS_Interpret, it really does as libcxxabi __gxx_personality_v0 does!</div><div>So, I have a question, <b>can we inline libcxxabi __gxx_personality_v0 in _Unwind_Backtrace</b> to avoid external call to personality function like libgcc_s and old libcxx+gabi++, and it mays dies in some condition.</div><div>If it can, actually we should only pick up __gnu_unwind_frame() for personality function.</div><div><br></div><div>Regards.</div></div>