diff options
| author | Tamas Berghammer <tberghammer@google.com> | 2015-04-20 10:31:22 +0000 |
|---|---|---|
| committer | Tamas Berghammer <tberghammer@google.com> | 2015-04-20 10:31:22 +0000 |
| commit | c4ddfd865d83940890385b1bb25f1d8cdea8ee64 (patch) | |
| tree | 31888fb06f8ae45e862dfae3935f388fc28c8cc9 /lldb/source/Plugins/Process/Linux | |
| parent | 35856696b8d42536052e5c757e3ee2b133261e0f (diff) | |
| download | bcm5719-llvm-c4ddfd865d83940890385b1bb25f1d8cdea8ee64.tar.gz bcm5719-llvm-c4ddfd865d83940890385b1bb25f1d8cdea8ee64.zip | |
Auto advance pc for signle stepping on arm when emulation failes
The arm instruction emulation handles only some of the opcode (including
all of them modifying the PC). For the rest of the instructions we can
advance the PC by the size of the instruction as they don't modify the
PC on any other way.
Differential revision: http://reviews.llvm.org/D9076
llvm-svn: 235292
Diffstat (limited to 'lldb/source/Plugins/Process/Linux')
| -rw-r--r-- | lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp | 54 |
1 files changed, 37 insertions, 17 deletions
diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp index e027939975e..f89403358b2 100644 --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -3894,16 +3894,25 @@ WriteRegisterCallback (EmulateInstruction *instruction, return true; } -static size_t WriteMemoryCallback (EmulateInstruction *instruction, - void *baton, - const EmulateInstruction::Context &context, - lldb::addr_t addr, - const void *dst, - size_t length) +static size_t +WriteMemoryCallback (EmulateInstruction *instruction, + void *baton, + const EmulateInstruction::Context &context, + lldb::addr_t addr, + const void *dst, + size_t length) { return length; } +static lldb::addr_t +ReadCpsr (NativeRegisterContext* regsiter_context) +{ + const RegisterInfo* cpsr_info = regsiter_context->GetRegisterInfo( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); + return regsiter_context->ReadRegisterAsUnsigned(cpsr_info, LLDB_INVALID_ADDRESS); +} + Error NativeProcessLinux::SingleStep(lldb::tid_t tid, uint32_t signo) { @@ -3914,7 +3923,7 @@ NativeProcessLinux::SingleStep(lldb::tid_t tid, uint32_t signo) EmulateInstruction::FindPlugin(m_arch, eInstructionTypePCModifying, nullptr)); if (emulator_ap == nullptr) - return Error("Instrunction emulator not found!"); + return Error("Instruction emulator not found!"); EmulatorBaton baton(this, register_context_sp.get()); emulator_ap->SetBaton(&baton); @@ -3926,20 +3935,31 @@ NativeProcessLinux::SingleStep(lldb::tid_t tid, uint32_t signo) if (!emulator_ap->ReadInstruction()) return Error("Read instruction failed!"); - if (!emulator_ap->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC)) - return Error("Evaluate instrcution failed!"); - - lldb::addr_t next_pc = baton.m_pc.GetAsUInt32(); - lldb::addr_t next_cpsr = 0; - if (baton.m_cpsr.GetType() != RegisterValue::eTypeInvalid) + lldb::addr_t next_pc; + lldb::addr_t next_cpsr; + if (emulator_ap->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC)) { - next_cpsr = baton.m_cpsr.GetAsUInt32(); + next_pc = baton.m_pc.GetAsUInt32(); + if (baton.m_cpsr.GetType() != RegisterValue::eTypeInvalid) + next_cpsr = baton.m_cpsr.GetAsUInt32(); + else + next_cpsr = ReadCpsr (register_context_sp.get()); + } + else if (baton.m_pc.GetType() == RegisterValue::eTypeInvalid) + { + // Emulate instruction failed and it haven't changed PC. Advance PC + // with the size of the current opcode because the emulation of all + // PC modifying instruction should be successful. The failure most + // likely caused by a not supported instruction which don't modify PC. + next_pc = register_context_sp->GetPC() + emulator_ap->GetOpcode().GetByteSize(); + next_cpsr = ReadCpsr (register_context_sp.get()); } else { - const RegisterInfo* cpsr_info = register_context_sp->GetRegisterInfo( - eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); - next_cpsr = register_context_sp->ReadRegisterAsUnsigned(cpsr_info, LLDB_INVALID_ADDRESS); + // The instruction emulation failed after it modified the PC. It is an + // unknown error where we can't continue because the next instruction is + // modifying the PC but we don't know how. + return Error ("Instruction emulation failed unexpectedly."); } if (next_cpsr & 0x20) |

