From a7d7f7cf3301f9768e807d024836c5ac9e71a7b8 Mon Sep 17 00:00:00 2001 From: Omair Javaid Date: Tue, 5 Jan 2016 16:56:13 +0000 Subject: Fix for undefined behavior while updating PC value on arm-linux Differential revision: http://reviews.llvm.org/D15877 llvm-svn: 256847 --- .../Process/Linux/NativeRegisterContextLinux_arm.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'lldb/source/Plugins/Process') diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp index ba32840e194..31752fed5b4 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp @@ -973,7 +973,24 @@ NativeRegisterContextLinux_arm::DoWriteRegisterValue(uint32_t offset, if (error.Fail()) return error; - m_gpr_arm[offset / sizeof(uint32_t)] = value.GetAsUInt32(); + uint32_t reg_value = value.GetAsUInt32(); + // As precaution for an undefined behavior encountered while setting PC we + // will clear thumb bit of new PC if we are already in thumb mode; that is + // CPSR thumb mode bit is set. + if (offset / sizeof(uint32_t) == gpr_pc_arm) + { + // Check if we are already in thumb mode and + // thumb bit of current PC is read out to be zero and + // thumb bit of next PC is read out to be one. + if ((m_gpr_arm[gpr_cpsr_arm] & 0x20) && + !(m_gpr_arm[gpr_pc_arm] & 0x01) && + (value.GetAsUInt32() & 0x01)) + { + reg_value &= (~1ull); + } + } + + m_gpr_arm[offset / sizeof(uint32_t)] = reg_value; return DoWriteGPR(m_gpr_arm, sizeof(m_gpr_arm)); } -- cgit v1.2.3