For Android Native developers, they may often encounter the problem of Native Crash in the development process and online environment. For such Native Crash, we usually directly adDR2line or use the NDK-Stack script attached to NDK for analysis. However, the NDK-Stack does not analyze libraries with mismatched build ids. For the above problems, we can try to analyze them even if the build ID is different. The general process is as follows:

Based on this analysis process, I wrote an AS plug-in: SmartNDKStack, which has the following functions:

  1. You can upload logs or select log analysis. Hyperlinks are displayed for parsing results
  2. Resolve based on function offset when buildId does not match
  3. Expand inline call
  4. Select the ELF file to resolve the build ID in the Project view
  5. Specify the NDK path
  6. Specify the symbol library directory

If you need it, you can search for it in the plugin market. Now there may be some shortcomings, if there is a problem, please send me the screenshots and symptom description: [email protected]

The following is a description of the principle.

1. Description of call stack frame content

Write a demo to trigger crash

__attribute__((always_inline)) void realThrowFatal(a){
    raise(SIGABRT);
}
__attribute__((always_inline)) void throwFatal(a){
    realThrowFatal(a); }extern "C" JNIEXPORT jstring JNICALL
Java_com_example_ndkdemo_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    throwFatal(a);return env->NewStringUTF(hello.c_str());
}
Copy the code

Run the call stack

The 2021-11-14 16:04:45. 573, 14705-14705 /? A/DEBUG: #00 pc 00000000000c5008 /apex/com.android.runtime/lib64/bionic/libc.so (tgkill+8) (BuildId: E81bf516b888e895d4e757da439c8117) 2021-11-14 16:04:45.? 574, 14705-14705 / A/DEBUG: #01 pc 000000000000f0c8 /data/app/~~NiGDTVWkvUzCYf_UpH7RdQ==/com.example.ndkdemo-dfk3WrVVoUG5N0jUHQiyyw==/lib/arm64/libndkdemo.so (Java_com_example_ndkdemo_MainActivity_stringFromJNI+52) (BuildId: 8 c26841b3c32a89935d095d8e916180628bded7b) 16:04:45. 2021-11-14? 574, 14705-14705 / A/DEBUG: #02 pc 000000000013ced4 /apex/com.android.art/lib64/libart.so (art_quick_generic_jni_trampoline+148) (BuildId: 9f1408149c58982ae91ee6377c202d2b) ...Copy the code

The image version:

For the above call stack,# 01Is the most concerned developers, hanging in their own library.

The key message reads as follows:

  1. The absolute path of the crash library on the local machine is/data/app/~~NiGDTVWkvUzCYf_UpH7RdQ==/com.example.ndkdemo-dfk3WrVVoUG5N0jUHQiyyw==/lib/arm64/libndkdemo.so
  2. The offset of the crash address relative to the library is0xf0c8
  3. Crash address is in the functionJava_com_example_ndkdemo_MainActivity_stringFromJNI, the offset with respect to the function address is52 (Decimal)
  4. The BuildId of crash’s library is8c26841b3c32a89935d095d8e916180628bded7b

2. How to parse

  • Normal operation

    addr2line -Cfie libndkdemo.so 0xf0c8

    Most tutorials on the Internet are conducted directly with the above adDR2line operation, which can indeed quickly locate the crash caused by direct operation in the development process. However, if the code has changed and the library does not match, the locating efficiency will be greatly reduced. For example, the test reported the crash, but the local code has changed and the library does not match. If you want to get a library with the same build ID, go back to the original code and create a new library with the same build ID for addr2line.

  • Advanced operation

    As shown in the above flow chart, we can first confirm the address of the function in the local library, and then add the address with the offset of the function to get the new address for resolution.

    • Get function address

    • parsing

      The address of the function is 0xf094, plus 52 in decimal, which means 0xf094 + 0x34 is exactly 0xf0C8, matching. We can still use this scheme resolution in the case of changes to the local library file (but make sure the change is not related to the current function).

    • The local library has changed

      Modify other functions so that the address of the function where crash is located is changed. After the change, the address of the function is 0xf0A0, 0xf0A0 + 0x34 = 0xf0D4. The new address addr2line is used, which can be found. 8 c26841b3c32a89935d095d8e916180628bded7b), but it can still parsing.