diff --git a/lldb/source/API/SystemInitializerFull.cpp b/lldb/source/API/SystemInitializerFull.cpp index 9b941965800e..a1edd8fee2a0 100644 --- a/lldb/source/API/SystemInitializerFull.cpp +++ b/lldb/source/API/SystemInitializerFull.cpp @@ -22,7 +22,6 @@ #include "Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h" #include "Plugins/Disassembler/llvm/DisassemblerLLVMC.h" #include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h" -#include "Plugins/Instruction/ARM/EmulateInstructionARM.h" #include "Plugins/Instruction/ARM64/EmulateInstructionARM64.h" #include "Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h" #include "Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h" @@ -251,7 +250,6 @@ SystemInitializerFull::Initialize() SymbolFileSymtab::Initialize(); UnwindAssemblyInstEmulation::Initialize(); UnwindAssembly_x86::Initialize(); - EmulateInstructionARM::Initialize(); EmulateInstructionARM64::Initialize(); EmulateInstructionMIPS64::Initialize(); SymbolFileDWARFDebugMap::Initialize(); @@ -355,7 +353,6 @@ SystemInitializerFull::Terminate() SymbolFileSymtab::Terminate(); UnwindAssembly_x86::Terminate(); UnwindAssemblyInstEmulation::Terminate(); - EmulateInstructionARM::Terminate(); EmulateInstructionARM64::Terminate(); EmulateInstructionMIPS64::Terminate(); SymbolFileDWARFDebugMap::Terminate(); diff --git a/lldb/source/Initialization/SystemInitializerCommon.cpp b/lldb/source/Initialization/SystemInitializerCommon.cpp index e4a1a302026a..b57072f682b2 100644 --- a/lldb/source/Initialization/SystemInitializerCommon.cpp +++ b/lldb/source/Initialization/SystemInitializerCommon.cpp @@ -17,6 +17,7 @@ #include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h" #include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h" +#include "Plugins/Instruction/ARM/EmulateInstructionARM.h" #include "Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h" #include "Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h" #include "Plugins/ObjectFile/ELF/ObjectFileELF.h" @@ -110,6 +111,8 @@ SystemInitializerCommon::Initialize() PlatformKalimba::Initialize(); platform_android::PlatformAndroid::Initialize(); + EmulateInstructionARM::Initialize(); + //---------------------------------------------------------------------- // Apple/Darwin hosted plugins //---------------------------------------------------------------------- @@ -157,6 +160,8 @@ SystemInitializerCommon::Terminate() PlatformRemoteiOS::Terminate(); PlatformiOSSimulator::Terminate(); + EmulateInstructionARM::Terminate(); + #if defined(__APPLE__) DynamicLoaderDarwinKernel::Terminate(); ObjectFileMachO::Terminate(); diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp index 286e21afec50..f740669af778 100644 --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -24,6 +24,7 @@ // Other libraries and framework includes #include "lldb/Core/Debugger.h" +#include "lldb/Core/EmulateInstruction.h" #include "lldb/Core/Error.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" @@ -2375,6 +2376,19 @@ NativeProcessLinux::MonitorBreakpoint(lldb::pid_t pid, NativeThreadProtocolSP th if (log) log->Printf("NativeProcessLinux::%s() pid = %" PRIu64 " fixup: %s", __FUNCTION__, pid, error.AsCString()); + + auto it = m_threads_stepping_with_breakpoint.find(pid); + if (it != m_threads_stepping_with_breakpoint.end()) + { + Error error = RemoveBreakpoint (it->second); + if (error.Fail()) + if (log) + log->Printf("NativeProcessLinux::%s() pid = %" PRIu64 " remove stepping breakpoint: %s", + __FUNCTION__, pid, error.AsCString()); + + m_threads_stepping_with_breakpoint.erase(it); + std::static_pointer_cast(thread_sp)->SetStoppedByTrace(); + } } else if (log) @@ -3590,6 +3604,151 @@ NativeProcessLinux::Resume (lldb::tid_t tid, uint32_t signo) return op.GetError(); } +#if defined(__arm__) + +namespace { + +struct EmulatorBaton +{ + NativeProcessLinux* m_process; + NativeRegisterContext* m_reg_context; + RegisterValue m_pc; + RegisterValue m_cpsr; + + EmulatorBaton(NativeProcessLinux* process, NativeRegisterContext* reg_context) : + m_process(process), m_reg_context(reg_context) {} +}; + +} // anonymous namespace + +static size_t +ReadMemoryCallback (EmulateInstruction *instruction, + void *baton, + const EmulateInstruction::Context &context, + lldb::addr_t addr, + void *dst, + size_t length) +{ + EmulatorBaton* emulator_baton = static_cast(baton); + + lldb::addr_t bytes_read; + emulator_baton->m_process->ReadMemory(addr, dst, length, bytes_read); + return bytes_read; +} + +static bool +ReadRegisterCallback (EmulateInstruction *instruction, + void *baton, + const RegisterInfo *reg_info, + RegisterValue ®_value) +{ + EmulatorBaton* emulator_baton = static_cast(baton); + + // 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. + const RegisterInfo* full_reg_info = emulator_baton->m_reg_context->GetRegisterInfo( + eRegisterKindDWARF, reg_info->kinds[eRegisterKindDWARF]); + + Error error = emulator_baton->m_reg_context->ReadRegister(full_reg_info, reg_value); + return error.Success(); +} + +static bool +WriteRegisterCallback (EmulateInstruction *instruction, + void *baton, + const EmulateInstruction::Context &context, + const RegisterInfo *reg_info, + const RegisterValue ®_value) +{ + EmulatorBaton* emulator_baton = static_cast(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_cpsr = reg_value; + break; + } + + return true; +} + +static size_t WriteMemoryCallback (EmulateInstruction *instruction, + void *baton, + const EmulateInstruction::Context &context, + lldb::addr_t addr, + const void *dst, + size_t length) +{ + return length; +} + +Error +NativeProcessLinux::SingleStep(lldb::tid_t tid, uint32_t signo) +{ + Error error; + NativeRegisterContextSP register_context_sp = GetThreadByID(tid)->GetRegisterContext(); + + std::unique_ptr emulator_ap( + EmulateInstruction::FindPlugin(m_arch, eInstructionTypePCModifying, nullptr)); + + if (emulator_ap == nullptr) + return Error("Instrunction emulator not found!"); + + EmulatorBaton baton(this, register_context_sp.get()); + emulator_ap->SetBaton(&baton); + emulator_ap->SetReadMemCallback(&ReadMemoryCallback); + emulator_ap->SetReadRegCallback(&ReadRegisterCallback); + emulator_ap->SetWriteMemCallback(&WriteMemoryCallback); + emulator_ap->SetWriteRegCallback(&WriteRegisterCallback); + + 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) + { + next_cpsr = baton.m_cpsr.GetAsUInt32(); + } + 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); + } + + if (next_cpsr & 0x20) + { + // Thumb mode + error = SetBreakpoint(next_pc, 2, false); + } + else + { + // Arm mode + error = SetBreakpoint(next_pc, 4, false); + } + + if (error.Fail()) + return error; + + m_threads_stepping_with_breakpoint.emplace(tid, next_pc); + + error = Resume(tid, signo); + if (error.Fail()) + return error; + + return Error(); +} + +#else // defined(__arm__) + Error NativeProcessLinux::SingleStep(lldb::tid_t tid, uint32_t signo) { @@ -3598,6 +3757,8 @@ NativeProcessLinux::SingleStep(lldb::tid_t tid, uint32_t signo) return op.GetError(); } +#endif // defined(__arm__) + Error NativeProcessLinux::GetSignalInfo(lldb::tid_t tid, void *siginfo) { diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h index be205f8e4a4f..f44980d3daf5 100644 --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h @@ -192,6 +192,10 @@ namespace process_linux { std::unique_ptr m_coordinator_up; HostThread m_coordinator_thread; + // List of thread ids stepping with a breakpoint with the address of + // the relevan breakpoint + std::map m_threads_stepping_with_breakpoint; + struct OperationArgs { OperationArgs(NativeProcessLinux *monitor);