Fix the 16 bit/32 bit instruction check for arm.
The current code only looks for a branch, instead make this more
general.
Change-Id: Ib442d6f2f04074e274b320ca0cf04734cc78e5d2
diff --git a/libc/bionic/debug_stacktrace.cpp b/libc/bionic/debug_stacktrace.cpp
index 4100911..b49a42e 100644
--- a/libc/bionic/debug_stacktrace.cpp
+++ b/libc/bionic/debug_stacktrace.cpp
@@ -90,15 +90,22 @@
// Modify the pc to point at the real function.
if (ip != 0) {
#if defined(__arm__)
- // 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.
- short* ptr = reinterpret_cast<short*>(ip);
- // Thumb BLX(2)
- if ((*(ptr-1) & 0xff80) == 0x4780) {
- ip -= 2;
- } else {
- ip -= 4;
+ // If the ip is suspiciously low, do nothing to avoid a segfault trying
+ // to access this memory.
+ if (ip >= 4096) {
+ // Check bits [15:11] of the first halfword assuming the instruction
+ // is 32 bits long. If the bits are any of these values, then our
+ // assumption was correct:
+ // b11101
+ // b11110
+ // b11111
+ // Otherwise, this is a 16 bit instruction.
+ uint16_t value = (*reinterpret_cast<uint16_t*>(ip - 2)) >> 11;
+ if (value == 0x1f || value == 0x1e || value == 0x1d) {
+ ip -= 4;
+ } else {
+ ip -= 2;
+ }
}
#elif defined(__aarch64__)
// All instructions are 4 bytes long, skip back one instruction.