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
This commit is contained in:
Christopher Ferris 2015-08-25 20:48:46 -07:00
parent 4d7d05bd60
commit b72c9d80ab

View File

@ -90,15 +90,22 @@ static _Unwind_Reason_Code trace_function(__unwind_context* context, void* arg)
// Modify the pc to point at the real function. // Modify the pc to point at the real function.
if (ip != 0) { if (ip != 0) {
#if defined(__arm__) #if defined(__arm__)
// We need to do a quick check here to find out if the previous // If the ip is suspiciously low, do nothing to avoid a segfault trying
// instruction is a Thumb-mode BLX(2). If so subtract 2 otherwise // to access this memory.
// 4 from PC. if (ip >= 4096) {
short* ptr = reinterpret_cast<short*>(ip); // Check bits [15:11] of the first halfword assuming the instruction
// Thumb BLX(2) // is 32 bits long. If the bits are any of these values, then our
if ((*(ptr-1) & 0xff80) == 0x4780) { // assumption was correct:
ip -= 2; // b11101
} else { // 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; ip -= 4;
} else {
ip -= 2;
}
} }
#elif defined(__aarch64__) #elif defined(__aarch64__)
// All instructions are 4 bytes long, skip back one instruction. // All instructions are 4 bytes long, skip back one instruction.