[Lldb-commits] [lldb] r235852 - Fix register read callback in linux-arm single stepping
Pavel Labath
labath at google.com
Mon Apr 27 02:21:15 PDT 2015
Author: labath
Date: Mon Apr 27 04:21:14 2015
New Revision: 235852
URL: http://llvm.org/viewvc/llvm-project?rev=235852&view=rev
Log:
Fix register read callback in linux-arm single stepping
The previous read callback always read the value of the register what
caused problems when the emulator wrote some value into a register and
then expected to read the same value back. This CL add a register value
cache into the callbacks to return the correct value after a register
write also.
Test Plan: Stepping over BL/BLX instruction works on android-arm if the instruction set isn't change (other, unrelated patch will come for the case when we move to an other instruction set)
Reviewers: omjavaid, sas, clayborg
Reviewed By: clayborg
Subscribers: labath, tberghammer, rengolin, aemerson, lldb-commits
Differential Revision: http://reviews.llvm.org/D9187
From: Tamas Berghammer <tberghammer at google.com>
Modified:
lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
Modified: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp?rev=235852&r1=235851&r2=235852&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp Mon Apr 27 04:21:14 2015
@@ -2738,10 +2738,11 @@ struct EmulatorBaton
{
NativeProcessLinux* m_process;
NativeRegisterContext* m_reg_context;
- RegisterValue m_pc;
- RegisterValue m_flags;
- EmulatorBaton(NativeProcessLinux* process, NativeRegisterContext* reg_context) :
+ // eRegisterKindDWARF -> RegsiterValue
+ std::unordered_map<uint32_t, RegisterValue> m_register_values;
+
+ EmulatorBaton(NativeProcessLinux* process, NativeRegisterContext* reg_context) :
m_process(process), m_reg_context(reg_context) {}
};
@@ -2770,6 +2771,13 @@ ReadRegisterCallback (EmulateInstruction
{
EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton);
+ auto it = emulator_baton->m_register_values.find(reg_info->kinds[eRegisterKindDWARF]);
+ if (it != emulator_baton->m_register_values.end())
+ {
+ reg_value = it->second;
+ return true;
+ }
+
// The emulator only fill in the dwarf regsiter numbers (and in some case
// the generic register numbers). Get the full register info from the
// register context based on the dwarf register numbers.
@@ -2777,7 +2785,12 @@ ReadRegisterCallback (EmulateInstruction
eRegisterKindDWARF, reg_info->kinds[eRegisterKindDWARF]);
Error error = emulator_baton->m_reg_context->ReadRegister(full_reg_info, reg_value);
- return error.Success();
+ if (error.Success())
+ {
+ emulator_baton->m_register_values[reg_info->kinds[eRegisterKindDWARF]] = reg_value;
+ return true;
+ }
+ return false;
}
static bool
@@ -2788,17 +2801,7 @@ WriteRegisterCallback (EmulateInstructio
const RegisterValue ®_value)
{
EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton);
-
- switch (reg_info->kinds[eRegisterKindGeneric])
- {
- case LLDB_REGNUM_GENERIC_PC:
- emulator_baton->m_pc = reg_value;
- break;
- case LLDB_REGNUM_GENERIC_FLAGS:
- emulator_baton->m_flags = reg_value;
- break;
- }
-
+ emulator_baton->m_register_values[reg_info->kinds[eRegisterKindDWARF]] = reg_value;
return true;
}
@@ -2843,17 +2846,27 @@ NativeProcessLinux::SetupSoftwareSingleS
if (!emulator_ap->ReadInstruction())
return Error("Read instruction failed!");
+ bool emulation_result = emulator_ap->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC);
+
+ const RegisterInfo* reg_info_pc = register_context_sp->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+ const RegisterInfo* reg_info_flags = register_context_sp->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
+
+ auto pc_it = baton.m_register_values.find(reg_info_pc->kinds[eRegisterKindDWARF]);
+ auto flags_it = baton.m_register_values.find(reg_info_flags->kinds[eRegisterKindDWARF]);
+
lldb::addr_t next_pc;
lldb::addr_t next_flags;
- if (emulator_ap->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC))
+ if (emulation_result)
{
- next_pc = baton.m_pc.GetAsUInt64();
- if (baton.m_flags.GetType() != RegisterValue::eTypeInvalid)
- next_flags = baton.m_flags.GetAsUInt32();
+ assert(pc_it != baton.m_register_values.end() && "Emulation was successfull but PC wasn't updated");
+ next_pc = pc_it->second.GetAsUInt64();
+
+ if (flags_it != baton.m_register_values.end())
+ next_flags = flags_it->second.GetAsUInt64();
else
next_flags = ReadFlags (register_context_sp.get());
}
- else if (baton.m_pc.GetType() == RegisterValue::eTypeInvalid)
+ else if (pc_it == baton.m_register_values.end())
{
// Emulate instruction failed and it haven't changed PC. Advance PC
// with the size of the current opcode because the emulation of all
@@ -2889,7 +2902,6 @@ NativeProcessLinux::SetupSoftwareSingleS
error = SetSoftwareBreakpoint(next_pc, 0);
}
-
if (error.Fail())
return error;
More information about the lldb-commits
mailing list