From 52171b9bdcb2aa1efe9c4deab37c029699fe763d Mon Sep 17 00:00:00 2001 From: Ben Cheng Date: Tue, 7 May 2013 14:22:43 -0700 Subject: [PATCH] Adjust PC value in ARM stack trace. -2 for Thumb BLX(2) or -4 for the rest. Change-Id: I804fdabfa1db4709bede222d4b432e8d42d53167 --- libc/bionic/debug_stacktrace.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/libc/bionic/debug_stacktrace.cpp b/libc/bionic/debug_stacktrace.cpp index 87dbba3d9..5e8a40103 100644 --- a/libc/bionic/debug_stacktrace.cpp +++ b/libc/bionic/debug_stacktrace.cpp @@ -91,6 +91,27 @@ static _Unwind_Reason_Code trace_function(__unwind_context* context, void* arg) return _URC_NO_REASON; } +#ifdef __arm__ + /* + * The instruction pointer is pointing at the instruction after the bl(x), and + * the _Unwind_Backtrace routine already masks the Thumb mode indicator (LSB + * in PC). So we need to do a quick check here to find out if the previous + * instruction is a Thumb-mode BLX(2). If so subtract 2 otherwise 4 from PC. + */ + if (ip != 0) { + short* ptr = reinterpret_cast(ip); + // Thumb BLX(2) + + // FIXME - GCC 4.7 seems to have a bug as without the unnecessary cast to + // short the test will never pass. + if ((*(ptr-1) & 0xff80) == (short) 0x4780) { + ip -= 2; + } else { + ip -= 4; + } + } +#endif + state->frames[state->frame_count++] = ip; return (state->frame_count >= state->max_depth) ? _URC_END_OF_STACK : _URC_NO_REASON; }