diff options
| author | Omair Javaid <omair.javaid@linaro.org> | 2016-01-05 16:56:13 +0000 |
|---|---|---|
| committer | Omair Javaid <omair.javaid@linaro.org> | 2016-01-05 16:56:13 +0000 |
| commit | a7d7f7cf3301f9768e807d024836c5ac9e71a7b8 (patch) | |
| tree | ee6c7840010ac3f8a92a95527ed1ab543be3ae8b /lldb/source/Plugins/Process/Linux | |
| parent | c7b073a23a92eb6e88111972075bdaeeb29d4d07 (diff) | |
| download | bcm5719-llvm-a7d7f7cf3301f9768e807d024836c5ac9e71a7b8.tar.gz bcm5719-llvm-a7d7f7cf3301f9768e807d024836c5ac9e71a7b8.zip | |
Fix for undefined behavior while updating PC value on arm-linux
Differential revision: http://reviews.llvm.org/D15877
llvm-svn: 256847
Diffstat (limited to 'lldb/source/Plugins/Process/Linux')
| -rw-r--r-- | lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp | 19 |
1 files changed, 18 insertions, 1 deletions
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)); } |

