Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dump native callstack programmatically in Android #50

Closed
dipankar08 opened this issue Mar 28, 2016 · 11 comments
Closed

Dump native callstack programmatically in Android #50

dipankar08 opened this issue Mar 28, 2016 · 11 comments

Comments

@dipankar08
Copy link

Hello,

I am working on adding debuggability to my app when there is a crash. I want to detect callstack when there is unhandled exception in native code and dump it into the ADB logs. For that, I am using _Unwind_Backtrace API to capture current stack trace and abi::__cxa_demangle to de-mangle it.

With this approach:

  1. We are getting all invalid IP (Instruction pointer address) for ARM builds
  2. In some instances, we get partially correct stack for X86 build
  3. In some instances, we are getting full accurate stack for x86 build

Can you please help me out how can we get the correct callstack for ARM and all builds of X86? Is this is a known bug for clang? If yes, is there a workaround I can use?

The code snippet below highlights the technique I use to get stack trace and de-mangle it:

void DumpCallStack()
{
    const void* frames[MAX_DEPTH];

    StackCrawlState state;
    ….

    _Unwind_Backtrace(TraceStack, (void*)&state);
       ….
   DemangleAndLogStack(frames,countOfFrames);
}

void DemangleAndLogStack(const void** frames, size_t countOfFrames)
{
    for (int i = 0; i < (int) countOfFrames; i++)
    {
        void*       offs;
        char        namebuf[1024];
        const void* ip              = frames[i];
        const char* mangled_name    = LookupSymbol(ip, &offs, namebuf, sizeof(namebuf));

        int         status          = 0;
        char*       demangled       = 0;

        demangled = abi::__cxa_demangle(mangled_name, 0, 0, &status);

        if (status == 0 && demangled)
        {
            log (ANDROID_LOG_ERROR, "STACKTRACE", "Frame:[#%d] \tIP:[%p] \tFunction:[%s]", i, ip, demangled);
            free(demangled);
        }
        else 
        {
            log(ANDROID_LOG_ERROR, "STACKTRACE", "Frame:[#%d] \tIP:[%p] \tFunction:[%s]", i, ip, mangled_name);
        }
    }
}

OS Version: Android L (5.0.2)

Thanks,
Dipankar

@dipankar08
Copy link
Author

Here is the callstack. we are getting this for ARM build. As you can see the IP of the below stack is completely wrong.

03-08 17:27:17.796 19915 20022 E FOO       : #######################  EXCEPTION CALLSTACK  ######################### 
03-08 17:27:17.799 19915 20022 E STACKTRACE: Frame:[#0]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.799 19915 20022 E STACKTRACE: Frame:[#1]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.799 19915 20022 E STACKTRACE: Frame:[#2]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.800 19915 20022 E STACKTRACE: Frame:[#3]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.800 19915 20022 E STACKTRACE: Frame:[#4]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.800 19915 20022 E STACKTRACE: Frame:[#5]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.800 19915 20022 E STACKTRACE: Frame:[#6]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.800 19915 20022 E STACKTRACE: Frame:[#7]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.800 19915 20022 E STACKTRACE: Frame:[#8]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.800 19915 20022 E STACKTRACE: Frame:[#9]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.800 19915 20022 E STACKTRACE: Frame:[#10]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.800 19915 20022 E STACKTRACE: Frame:[#11]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.800 19915 20022 E STACKTRACE: Frame:[#12]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.800 19915 20022 E STACKTRACE: Frame:[#13]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.800 19915 20022 E STACKTRACE: Frame:[#14]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.800 19915 20022 E STACKTRACE: Frame:[#15]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.800 19915 20022 E STACKTRACE: Frame:[#16]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.801 19915 20022 E STACKTRACE: Frame:[#17]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.802 19915 20022 E STACKTRACE: Frame:[#18]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.803 19915 20022 E STACKTRACE: Frame:[#19]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.803 19915 20022 E STACKTRACE: Frame:[#20]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.803 19915 20022 E STACKTRACE: Frame:[#21]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.803 19915 20022 E STACKTRACE: Frame:[#22]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.803 19915 20022 E STACKTRACE: Frame:[#23]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.803 19915 20022 E STACKTRACE: Frame:[#24]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.803 19915 20022 E STACKTRACE: Frame:[#25]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.803 19915 20022 E STACKTRACE: Frame:[#26]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.803 19915 20022 E STACKTRACE: Frame:[#27]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.803 19915 20022 E STACKTRACE: Frame:[#28]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.803 19915 20022 E STACKTRACE: Frame:[#29]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]
03-08 17:27:17.803 19915 20022 E STACKTRACE: Frame:[#30]            IP:[0x70902cd4]       Function:[SetLastExceptionInfoForThread()]

BTW, there are an easier way to get the callstack in linux by using backtrace () as part of execinfo.h, which is not supported for Android. Do you have any plan to get this header/so inplace in future version of android ?

I am using clang compiler with androidndk.10.4.1 tool chain.

@DanAlbert
Copy link
Member

You don't need to backtrace yourself. debuggerd is a built in part of android that will print a backtrace of your app when it crashes.

As for fixing the underlying bug, we need more information. What STL are you using?

androidndk.10.4.1 tool chain

There's no such thing. Is that an Android Studio version? Are you using NDK r11b? If you're not using r11b, that's the first thing to check.

@dipankar08
Copy link
Author

Hello,

We are using r10d only as r10e had toolchain problems.
We are currently using clang3.5. and gcc4.9 (for support toolchain)
We are using stl library located at sources\cxx-stl\gnu-libstdc++ in the NDK.

Thanks
Dipankar

@DanAlbert
Copy link
Member

Reopen if this is still present in r11b. Clang has been completely redone (we threw away the old crappy hacked about source that was in the NDK and reset to upstream), so there's a significant chance the problem will go away just by upgrading.

@minggo
Copy link

minggo commented Aug 25, 2017

debuggerd is a built in part of android that will print a backtrace of your app when it crashes.

@DanAlbert does it work in release mode too? Can it work only using clang, or can also work with gcc?
Thanks.

@DanAlbert
Copy link
Member

As long as your app can be unwound (debuggerd will try a lot of different ways to do this), it will be unwound. Should work with essentially any binary.

@minggo
Copy link

minggo commented Aug 28, 2017

Thanks.
What does your app can be unwound mean?

@DanAlbert
Copy link
Member

As long as you haven't gone out of your way to obfuscate it then it should be fine.

@bsergean
Copy link

Hi there,

Computing a backtrace can be very helpful in other context, rather than just for handling crashes. For example in a large code base you can record where an API is used, and put that in an associative array (key = backtrace, value = hit-count). It can be used for ad'hoc memory leak detector etc...

Obviously I am not aware of the complexity of support this, but it would make the Android platform more developer friendly and comparable to other platform (this is available in Linux and macOS) to do so.

@enh
Copy link
Contributor

enh commented Aug 23, 2018

we're looking at adding <execinfo.h> (http://man7.org/linux/man-pages/man3/backtrace.3.html) in a future release.

@alexeikh
Copy link

alexeikh commented Sep 3, 2018

Before <execinfo.h> is added, maybe my small app for testing 3 backtracing methods on Android will be helpful for someone: https://github.com/alexeikh/android-ndk-backtrace-test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants