mstorsjo created this revision.
mstorsjo added a reviewer: labath.
Herald added a subscriber: kristof.beyls.
mstorsjo requested review of this revision.
Herald added a project: LLDB.
Based on suggestions by Eric Youngdale.
This fixes https://llvm.org/PR51673.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D109777
Files:
lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp
lldb/source/Plugins/Platform/Windows/PlatformWindows.h
lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.h
lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp
lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp
Index: lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp
===================================================================
--- lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp
+++ lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp
@@ -131,12 +131,29 @@
return Status();
if (resume_state == eStateStepping) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
+
uint32_t flags_index =
GetRegisterContext()->ConvertRegisterKindToRegisterNumber(
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
uint64_t flags_value =
GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0);
- flags_value |= 0x100; // Set the trap flag on the CPU
+ ProcessSP process = GetProcess();
+ const ArchSpec &arch = process->GetTarget().GetArchitecture();
+ switch (arch.GetMachine()) {
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ flags_value |= 0x100; // Set the trap flag on the CPU
+ break;
+ case llvm::Triple::aarch64:
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ flags_value |= 0x200000; // The SS bit in PState
+ break;
+ default:
+ LLDB_LOG(log, "single stepping unsupported on this architecture");
+ break;
+ }
GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value);
}
Index: lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
===================================================================
--- lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
+++ lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
@@ -438,8 +438,29 @@
case EXCEPTION_BREAKPOINT: {
RegisterContextSP register_context = stop_thread->GetRegisterContext();
- // The current EIP is AFTER the BP opcode, which is one byte.
- uint64_t pc = register_context->GetPC() - 1;
+ int breakpoint_size = 1;
+ switch (GetTarget().GetArchitecture().GetMachine()) {
+ case llvm::Triple::aarch64:
+ breakpoint_size = 4;
+ break;
+
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ breakpoint_size = 2;
+ break;
+
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ breakpoint_size = 1;
+ break;
+
+ default:
+ LLDB_LOG(log, "Unknown breakpoint size for architecture");
+ break;
+ }
+
+ // The current EIP is AFTER the BP opcode.
+ uint64_t pc = register_context->GetPC() - breakpoint_size;
BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc));
if (site) {
Index: lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp
===================================================================
--- lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp
+++ lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp
@@ -48,12 +48,29 @@
return Status();
if (resume_state == eStateStepping) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
+
uint32_t flags_index =
GetRegisterContext().ConvertRegisterKindToRegisterNumber(
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
uint64_t flags_value =
GetRegisterContext().ReadRegisterAsUnsigned(flags_index, 0);
- flags_value |= 0x100; // Set the trap flag on the CPU
+ NativeProcessProtocol &process = GetProcess();
+ const ArchSpec &arch = process.GetArchitecture();
+ switch (arch.GetMachine()) {
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ flags_value |= 0x100; // Set the trap flag on the CPU
+ break;
+ case llvm::Triple::aarch64:
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ flags_value |= 0x200000; // The SS bit in PState
+ break;
+ default:
+ LLDB_LOG(log, "single stepping unsupported on this architecture");
+ break;
+ }
GetRegisterContext().WriteRegisterFromUnsigned(flags_index, flags_value);
}
Index: lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.h
===================================================================
--- lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.h
+++ lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.h
@@ -108,6 +108,9 @@
protected:
NativeThreadWindows *GetThreadByID(lldb::tid_t thread_id);
+ llvm::Expected<llvm::ArrayRef<uint8_t>>
+ GetSoftwareBreakpointTrapOpcode(size_t size_hint) override;
+
bool FindSoftwareBreakpoint(lldb::addr_t addr);
void StopThread(lldb::tid_t thread_id, lldb::StopReason reason,
Index: lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
===================================================================
--- lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
+++ lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
@@ -289,6 +289,24 @@
return llvm::errc::not_supported;
}
+llvm::Expected<llvm::ArrayRef<uint8_t>>
+NativeProcessWindows::GetSoftwareBreakpointTrapOpcode(size_t size_hint) {
+ static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x3e, 0xd4}; // brk #0xf000
+ static const uint8_t g_thumb_opcode[] = {0xfe, 0xde}; // udf #0xfe
+
+ switch (GetArchitecture().GetMachine()) {
+ case llvm::Triple::aarch64:
+ return llvm::makeArrayRef(g_aarch64_opcode);
+
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ return llvm::makeArrayRef(g_thumb_opcode);
+
+ default:
+ return NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_hint);
+ }
+}
+
bool NativeProcessWindows::FindSoftwareBreakpoint(lldb::addr_t addr) {
auto it = m_software_breakpoints.find(addr);
if (it == m_software_breakpoints.end())
@@ -474,8 +492,28 @@
if (NativeThreadWindows *stop_thread =
GetThreadByID(record.GetThreadID())) {
auto ®ister_context = stop_thread->GetRegisterContext();
- // The current EIP is AFTER the BP opcode, which is one byte '0xCC'
- uint64_t pc = register_context.GetPC() - 1;
+ int breakpoint_size = 1;
+ switch (GetArchitecture().GetMachine()) {
+ case llvm::Triple::aarch64:
+ breakpoint_size = 4;
+ break;
+
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ breakpoint_size = 2;
+ break;
+
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ breakpoint_size = 1;
+ break;
+
+ default:
+ LLDB_LOG(log, "Unknown breakpoint size for architecture");
+ break;
+ }
+ // The current PC is AFTER the BP opcode.
+ uint64_t pc = register_context.GetPC() - breakpoint_size;
register_context.SetPC(pc);
}
Index: lldb/source/Plugins/Platform/Windows/PlatformWindows.h
===================================================================
--- lldb/source/Plugins/Platform/Windows/PlatformWindows.h
+++ lldb/source/Plugins/Platform/Windows/PlatformWindows.h
@@ -63,6 +63,9 @@
void CalculateTrapHandlerSymbolNames() override {}
ConstString GetFullNameForDylib(ConstString basename) override;
+
+ size_t GetSoftwareBreakpointTrapOpcode(Target &target,
+ BreakpointSite *bp_site) override;
};
} // namespace lldb_private
Index: lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp
===================================================================
--- lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp
+++ lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp
@@ -312,3 +312,38 @@
stream.Printf("%s.dll", basename.GetCString());
return ConstString(stream.GetString());
}
+
+size_t
+PlatformWindows::GetSoftwareBreakpointTrapOpcode(Target &target,
+ BreakpointSite *bp_site) {
+ ArchSpec arch = target.GetArchitecture();
+ assert(arch.IsValid());
+ const uint8_t *trap_opcode = nullptr;
+ size_t trap_opcode_size = 0;
+
+ switch (arch.GetMachine()) {
+ case llvm::Triple::aarch64: {
+ static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x3e, 0xd4}; // brk #0xf000
+ trap_opcode = g_aarch64_opcode;
+ trap_opcode_size = sizeof(g_aarch64_opcode);
+
+ if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
+ return trap_opcode_size;
+ return 0;
+ } break;
+
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb: {
+ static const uint8_t g_thumb_opcode[] = {0xfe, 0xde}; // udf #0xfe
+ trap_opcode = g_thumb_opcode;
+ trap_opcode_size = sizeof(g_thumb_opcode);
+
+ if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
+ return trap_opcode_size;
+ return 0;
+ } break;
+
+ default:
+ return Platform::GetSoftwareBreakpointTrapOpcode(target, bp_site);
+ }
+}
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits