2

When my Android app crashes (or hits an assert), I never get more than four lines of backtrace. Searching for similar problems, I've only found one or two places where this is mentioned and the stock responses are: "make sure it's a debug build" and "you probably have stack corruption". I have seen many crashes occur in many places with accurate-looking frames and no evidence of corruption.

Here's a typical excerpt taken from `adb logcat' following an assert failure in a debug build:

I/DEBUG   (  187):     d28 3f824fc6ced25306  d29 3fabdfebb8fe14dc
I/DEBUG   (  187):     d30 fff0000000000000  d31 fffffffeffffffd2
I/DEBUG   (  187):     scr 88000010
I/DEBUG   (  187): 
I/DEBUG   (  187): backtrace:
I/DEBUG   (  187):     #00  pc 00018516  /system/lib/libc.so
I/DEBUG   (  187):     #01  pc 0000dc44  /system/lib/libc.so (abort+4)
I/DEBUG   (  187):     #02  pc 0000168d  /system/lib/liblog.so (__android_log_assert+88)
I/DEBUG   (  187):     #03  pc 00170bcc  /data/data/com.jsam.crag/lib/libmain.so (sim::TouchObserverController::HandleEvent(SDL_Event const&)+340)
I/DEBUG   (  187): 
I/DEBUG   (  187): stack:
I/DEBUG   (  187):          6f4be770  6f4be76c  [stack:17025]
I/DEBUG   (  187):          6f4be774  00000000  
I/DEBUG   (  187):          6f4be778  00000000  

As you can see, most of the available backtrace isn't even in my own code. I'm developing on a developer edition HTC One with out-of-box OS, using release 8e of the NDK and building against android-10, although android-15 is no different. I'm using toolchain v4.7, the gnustl_static STL and my C++ flags are:

-std=c++11 -g -pthread -DPROFILE -D__STRICT_ANSI__ -DdSINGLE -Wall -Wextra -Wfatal-errors -fno-rtti -fno-exceptions

How would I go about getting longer (preferably complete) backtraces?

John McFarlane
  • 5,528
  • 4
  • 34
  • 38

3 Answers3

1

You can use gdb for native application debuging on android, see Generate core dump in android

This can give you more then just stack trace.

Community
  • 1
  • 1
fghj
  • 8,898
  • 4
  • 28
  • 56
  • Thanks. This is very useful when debugging the app, but if it has crashed before I attach the debugger, I assume that logcat is my only source of info. (I'd be pretty surprised if Android apps dumped out a core file.) – John McFarlane Jul 15 '13 at 20:09
  • In another topic (can not find link now) there was note, that on rooted device if you run console application core dump works, if you use analog of ulimit -c unlimited. But if java code involved core dump not works, may this is because of java runtime disable it somewhere. – fghj Jul 17 '13 at 00:22
  • Thanks. I will look in to this although I'm pretty sure both my phones are unlocked and only one of them has this limitation. – John McFarlane Jul 17 '13 at 16:55
  • Thanks, I'll look into this although I'm pretty sure both of my phones are unlocked but only one has this limitation when the same binary is run on them. – John McFarlane Jul 17 '13 at 16:57
1

The debuggerd stack trace mechanism uses the exception-unwinding mechanism to walk up the tree. This is enabled with the gcc -funwind-tables argument.

gdb ignores those and uses its own mechanism, which relies on disassembling the code to figure out where the return value lives on the stack. This usually works for gcc-generated code but can get confused. Sometimes gdb or debuggerd will be able to decode a stack trace that the other can't.

(edit: more notes)

The basic problem is that the compiler is configured to generate code that doesn't use a frame pointer. The caller puts the return address in the LR register, and the called function branches to it when done. LR is a general-purpose register, so it's common to spill it to the stack and restore it right before returning. The code that traverses the stack needs to figure out if it has been spilled, and if so, where on the stack it may be found.

For some reason debuggerd doesn't seem to think it can traverse farther up the stack. One reason would be the absence of unroll information.

fadden
  • 51,356
  • 5
  • 116
  • 166
  • Thanks for the info. I did try adding -funwind-tables but it didn't make any noticeable difference. debuggerd (or whatever is producing the information found with logcat) seems to have absolutely no problem symbolicating the top four lines of stack; it consistently prints four lines of accurate information and no more. It looks to all the world like somewhere, the information is deliberately capped - possibly to economize on logger output. – John McFarlane Jul 15 '13 at 20:32
  • (I added a bit more detail to the answer.) There is a cap in debuggerd, but it's set to 32 frames. Try removing `-fno-exceptions`, or maybe make sure it's specified before `-funwind-tables`. I'm wondering if no-exceptions is disabling table generation. – fadden Jul 15 '13 at 23:38
  • Removing `-fno-exceptions` and adding `-funwind-table` didn't seem to make a difference. I notice that issuing `bt` from `ndk-gdb` now gives bad results, e.g. `#3 0x400c3690 in ?? ()`. Also, I created the same crash on a Nexus One (with CyanogenMod) and got a complete, but mangled, stack with function names such as: `_ZN3sim23TouchObserverController11HandleEventERK9SDL_Event`. So I'm now wondering whether it's the OS or the device which is problematic. – John McFarlane Jul 16 '13 at 02:19
  • If you have the `c++filt` tool you can paste the name in to get `sim::TouchObserverController::HandleEvent(SDL_Event const&)`. I think the `addr2line` tool does the un-mangling for you (see http://stackoverflow.com/questions/2314273/get-function-names-from-call-stack/2480465#2480465). Are the devices running different versions of Android? The implementation of debuggerd has changed over time (e.g. the introduction of `libcorkscrew` a few revs back). – fadden Jul 16 '13 at 04:29
  • Yup, the One is on 4.1.2 and the Nexus One is on 2.3.7. I'll definitely try and get more data points when I get an opportunity. – John McFarlane Jul 17 '13 at 16:56
0

The answer appears to be to upgrade to Android 4.3. My phone received an update today (the custom HTC version rolled out to developer edition devices) and the backtraces dumped to the system log now reveal a full stack. However, as @user1034749 suggests, getting to grips with GDB is a good alternative with many additional benefits.

John McFarlane
  • 5,528
  • 4
  • 34
  • 38