This revision was automatically updated to reflect the committed changes. Closed by commit rL256847: Fix for undefined behavior while updating PC value on arm-linux (authored by omjavaid).
Changed prior to commit: http://reviews.llvm.org/D15877?vs=43941&id=44015#toc Repository: rL LLVM http://reviews.llvm.org/D15877 Files: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp Index: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp +++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp @@ -973,7 +973,24 @@ 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)); }
Index: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp +++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp @@ -973,7 +973,24 @@ 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)); }
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits