[Lldb-commits] [lldb] [lldb][Windows] ignore loader breakpoints in system modules (PR #208233)
https://github.com/charles-zablit closed https://github.com/llvm/llvm-project/pull/208233 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][Windows] ignore loader breakpoints in system modules (PR #208233)
@@ -293,8 +297,12 @@ Status ProcessWindows::DoDestroy() {
Status ProcessWindows::DoHalt(bool &caused_stop) {
StateType state = GetPrivateState();
- if (state != eStateStopped)
-return HaltProcess(caused_stop);
+ if (state != eStateStopped) {
+m_pending_halt = true;
charles-zablit wrote:
On Windows there's no SIGSTOP to pause a debuggee. To pause a running process
from the debugger `DebugBreakProcess()` is used. It works by injecting a new
thread into the target process that executes an `int3` instruction. The `int3`
causes an `EXCEPTION_BREAKPOINT`.
`EXCEPTION_BREAKPOINT` is ambiguous because it can mean either of the
following, without side data to differentiate them:
- Did the debuggee hit a breakpoint lldb set?: real stop, report it.
- Is this the loader's startup int3?: ignore it.
- Is this the artificial int3 lldb just injected to implement `Halt/Interrupt`?
it's not a "real" breakpoint at all, ignore it.
`m_expecting_loader_int3` resolves the 2nd case.
`m_pending_halt` resolves the 3rd case.
https://github.com/llvm/llvm-project/pull/208233
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][Windows] ignore loader breakpoints in system modules (PR #208233)
https://github.com/charles-zablit deleted https://github.com/llvm/llvm-project/pull/208233 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][Windows] ignore loader breakpoints in system modules (PR #208233)
@@ -293,8 +297,12 @@ Status ProcessWindows::DoDestroy() {
Status ProcessWindows::DoHalt(bool &caused_stop) {
StateType state = GetPrivateState();
- if (state != eStateStopped)
-return HaltProcess(caused_stop);
+ if (state != eStateStopped) {
+m_pending_halt = true;
charles-zablit wrote:
The Halt comes in as a Debug Exception yes.
It's not a real debug exception, it's just a "virtual breakpoint" that ntdll
inserts when a process is spawned halted.
lldb currently treat it as a real breakpoint, which is unexpected to the user,
because lldb looks like it hit a breakpoint that does not exist.
The m_pending_halt essentially says "disregard the first halt breakpoint we hit"
https://github.com/llvm/llvm-project/pull/208233
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][Windows] ignore loader breakpoints in system modules (PR #208233)
@@ -293,8 +297,12 @@ Status ProcessWindows::DoDestroy() {
Status ProcessWindows::DoHalt(bool &caused_stop) {
StateType state = GetPrivateState();
- if (state != eStateStopped)
-return HaltProcess(caused_stop);
+ if (state != eStateStopped) {
+m_pending_halt = true;
jimingham wrote:
You need this because the stop from a Halt comes in as an EXCEPTION_BREAKPOINT?
https://github.com/llvm/llvm-project/pull/208233
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][Windows] ignore loader breakpoints in system modules (PR #208233)
https://github.com/Nerixyz approved this pull request. This looks good to me now. I think it should be noted that we only need to do this when attaching to a process. We notice this in lldb-dap when launching in a terminal, because that will attach to the process. The documentation for [`DebugActiveProcess`](https://learn.microsoft.com/en-us/windows/win32/api/debugapi/nf-debugapi-debugactiveprocess) also mentions this: > After all of this is done, the system resumes all threads in the process. > When the first thread in the process resumes, it executes a breakpoint > instruction that causes an EXCEPTION_DEBUG_EVENT debugging event to be sent > to the debugger. All future debugging events are sent to the debugger by > using the normal mechanism and rules. https://github.com/llvm/llvm-project/pull/208233 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][Windows] ignore loader breakpoints in system modules (PR #208233)
@@ -664,6 +627,17 @@ NativeProcessWindows::HandleBreakpointException(const
ExceptionRecord &record) {
return ExceptionResult::BreakInDebugger;
}
+ if (m_expecting_loader_int3) {
+m_expecting_loader_int3 = false;
charles-zablit wrote:
That's a bug. I moved the call to `IsSystemModuleAddress` up the chain in both
places where this happens.
https://github.com/llvm/llvm-project/pull/208233
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][Windows] ignore loader breakpoints in system modules (PR #208233)
https://github.com/charles-zablit edited https://github.com/llvm/llvm-project/pull/208233 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][Windows] ignore loader breakpoints in system modules (PR #208233)
@@ -19,16 +19,85 @@
#include "lldb/Host/ProcessLaunchInfo.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Process.h"
+#include "lldb/Utility/FileSpec.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Error.h"
#include "DebuggerThread.h"
#include "ExceptionRecord.h"
#include "ProcessWindowsLog.h"
+#include
+#include
+#include
+
using namespace lldb;
using namespace lldb_private;
+static void NormalizeWindowsPath(std::string &s) {
+ for (char &c : s) {
+if (c == '/')
+ c = '\\';
+else
+ c = std::tolower(static_cast(c));
+ }
+}
+
+bool ProcessDebugger::IsSystemDLL(const FileSpec &spec) {
+ if (!spec)
+return false;
+
+ static const std::string windows_prefix = []() {
+std::string prefix;
+wchar_t buf[MAX_PATH];
+UINT len = ::GetWindowsDirectoryW(buf, MAX_PATH);
+if (len == 0 || len >= MAX_PATH)
+ return prefix;
+llvm::convertWideToUTF8(std::wstring_view(buf, len), prefix);
+NormalizeWindowsPath(prefix);
+if (!prefix.empty() && prefix.back() != '\\')
+ prefix += '\\';
+return prefix;
+ }();
+
+ if (windows_prefix.empty())
+return false;
+
+ std::string path = spec.GetPath();
+ NormalizeWindowsPath(path);
+ return llvm::StringRef(path).starts_with(windows_prefix);
charles-zablit wrote:
Fixed
https://github.com/llvm/llvm-project/pull/208233
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][Windows] ignore loader breakpoints in system modules (PR #208233)
@@ -19,16 +19,85 @@
#include "lldb/Host/ProcessLaunchInfo.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Process.h"
+#include "lldb/Utility/FileSpec.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Error.h"
#include "DebuggerThread.h"
#include "ExceptionRecord.h"
#include "ProcessWindowsLog.h"
+#include
+#include
+#include
+
using namespace lldb;
using namespace lldb_private;
+static void NormalizeWindowsPath(std::string &s) {
+ for (char &c : s) {
+if (c == '/')
+ c = '\\';
+else
+ c = std::tolower(static_cast(c));
+ }
+}
+
+bool ProcessDebugger::IsSystemDLL(const FileSpec &spec) {
charles-zablit wrote:
Switched to `StringRef` 👍
https://github.com/llvm/llvm-project/pull/208233
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][Windows] ignore loader breakpoints in system modules (PR #208233)
https://github.com/charles-zablit updated
https://github.com/llvm/llvm-project/pull/208233
>From d6abb3698fd1419ec5c89df61a9243cf6fcc0772 Mon Sep 17 00:00:00 2001
From: Charles Zablit
Date: Wed, 8 Jul 2026 15:46:39 +0100
Subject: [PATCH 1/6] [lldb][Windows] ignore loader breakpoints in system
modules
---
.../Windows/Common/NativeProcessWindows.cpp | 55 ---
.../Windows/Common/ProcessDebugger.cpp| 69 +++
.../Process/Windows/Common/ProcessDebugger.h | 5 ++
.../Process/Windows/Common/ProcessWindows.cpp | 16 -
4 files changed, 101 insertions(+), 44 deletions(-)
diff --git
a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
index ada92894efc47..f1de697c34b67 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
@@ -50,44 +50,6 @@ using namespace llvm;
namespace lldb_private {
-namespace {
-
-void NormalizeWindowsPath(std::string &s) {
- for (char &c : s) {
-if (c == '/')
- c = '\\';
-else
- c = std::tolower(static_cast(c));
- }
-}
-
-bool IsSystemDLL(const FileSpec &spec) {
- if (!spec)
-return false;
-
- static const std::string windows_prefix = []() {
-std::string prefix;
-wchar_t buf[MAX_PATH];
-UINT len = ::GetWindowsDirectoryW(buf, MAX_PATH);
-if (len == 0 || len >= MAX_PATH)
- return prefix;
-llvm::convertWideToUTF8(std::wstring_view(buf, len), prefix);
-NormalizeWindowsPath(prefix);
-if (!prefix.empty() && prefix.back() != '\\')
- prefix += '\\';
-return prefix;
- }();
-
- if (windows_prefix.empty())
-return false;
-
- std::string path = spec.GetPath();
- NormalizeWindowsPath(path);
- return llvm::StringRef(path).starts_with(windows_prefix);
-}
-
-} // namespace
-
NativeProcessWindows::NativeProcessWindows(ProcessLaunchInfo &launch_info,
NativeDelegate &delegate,
llvm::Error &E)
@@ -635,9 +597,8 @@ NativeProcessWindows::HandleBreakpointException(const
ExceptionRecord &record) {
return ExceptionResult::BreakInDebugger;
}
- // Any remaining STATUS_BREAKPOINT is a breakpoint instruction in the
- // program's own code (e.g. `__debugbreak()` or `__builtin_debugtrap()`).
- // Stop the debugger and let the user decide what to do.
+ // Our own DebugBreakProcess() injection, used to implement
+ // Halt()/Interrupt().
if (m_pending_halt) {
LLDB_LOG(log,
"DebugBreakProcess injection treated as Halt SIGSTOP for tid "
@@ -664,6 +625,14 @@ NativeProcessWindows::HandleBreakpointException(const
ExceptionRecord &record) {
return ExceptionResult::BreakInDebugger;
}
+ if (IsSystemModuleAddress(exception_addr)) {
+LLDB_LOG(log,
+ "Ignoring loader/OS breakpoint at address {0:x} in a system "
+ "module.",
+ exception_addr);
+return ExceptionResult::MaskException;
+ }
+
std::string desc = formatv("Exception {0:x8} encountered at address {1:x8}",
record.GetExceptionValue(), exception_addr)
.str();
@@ -776,7 +745,7 @@ DllEventAction NativeProcessWindows::OnLoadDll(const
ModuleSpec &module_spec,
return DllEventAction::ContinueDebugLoop;
// Can't resolve a breakpoint in a system DLL.
- if (!resolved || IsSystemDLL(resolved))
+ if (!resolved || ProcessDebugger::IsSystemDLL(resolved))
return DllEventAction::ContinueDebugLoop;
NativeThreadWindows *loader_thread = GetThreadByID(thread_id);
@@ -819,7 +788,7 @@ DllEventAction
NativeProcessWindows::OnUnloadDll(lldb::addr_t module_addr,
if (!m_initial_stop_seen || !m_client_supports_libraries_read)
return DllEventAction::ContinueDebugLoop;
- if (!unloaded_spec || IsSystemDLL(unloaded_spec))
+ if (!unloaded_spec || ProcessDebugger::IsSystemDLL(unloaded_spec))
return DllEventAction::ContinueDebugLoop;
NativeThreadWindows *unloader_thread = GetThreadByID(thread_id);
diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
b/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
index 63fc20f36b07b..a4322c3d3f536 100644
--- a/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
@@ -19,6 +19,7 @@
#include "lldb/Host/ProcessLaunchInfo.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Process.h"
+#include "lldb/Utility/FileSpec.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Error.h"
@@ -26,9 +27,77 @@
#include "ExceptionRecord.h"
#include "ProcessWindowsLog.h"
+#include
+#include
+#include
+
using namespace lldb;
using namespace lldb_private;
+static void NormalizeWindowsPath(std::string &s) {
+ for (char &c : s) {
+if (c == '/')
[Lldb-commits] [lldb] [lldb][Windows] ignore loader breakpoints in system modules (PR #208233)
charles-zablit wrote: > What is the logic behind `m_pending_halt`? You set it in > `ProcessWindows::DoHalt` but then you also check for it when handling an > `EXCEPTION_BREAKPOINT`. Why do you need to check there? This is to tell appart `int3` exceptions we caused to interrupt the process, versus any other ones (real exceptions). When lldb halts a process, the process will be halted through an `EXCEPTION_BREAKPOINT` but there is no way to differentiate it with a real breakpoint. https://github.com/llvm/llvm-project/pull/208233 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][Windows] ignore loader breakpoints in system modules (PR #208233)
https://github.com/bulbazord commented: What is the logic behind `m_pending_halt`? You set it in `ProcessWindows::DoHalt` but then you also check for it when handling an `EXCEPTION_BREAKPOINT`. Why do you need to check there? https://github.com/llvm/llvm-project/pull/208233 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][Windows] ignore loader breakpoints in system modules (PR #208233)
charles-zablit wrote: The handler only runs for `STATUS_BREAKPOINT` whereas fatal errors use different instructions: `__builtin_trap()` uses `STATUS_ILLEGAL_INSTRUCTION` for instance. This means fatal errors exceptions don't enter `HandleBreakpointException` and are therefore not masked. I've narrowed down the int3 masking to one stop in the latest commit. https://github.com/llvm/llvm-project/pull/208233 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][Windows] ignore loader breakpoints in system modules (PR #208233)
https://github.com/charles-zablit updated
https://github.com/llvm/llvm-project/pull/208233
>From d6abb3698fd1419ec5c89df61a9243cf6fcc0772 Mon Sep 17 00:00:00 2001
From: Charles Zablit
Date: Wed, 8 Jul 2026 15:46:39 +0100
Subject: [PATCH 1/5] [lldb][Windows] ignore loader breakpoints in system
modules
---
.../Windows/Common/NativeProcessWindows.cpp | 55 ---
.../Windows/Common/ProcessDebugger.cpp| 69 +++
.../Process/Windows/Common/ProcessDebugger.h | 5 ++
.../Process/Windows/Common/ProcessWindows.cpp | 16 -
4 files changed, 101 insertions(+), 44 deletions(-)
diff --git
a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
index ada92894efc47..f1de697c34b67 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
@@ -50,44 +50,6 @@ using namespace llvm;
namespace lldb_private {
-namespace {
-
-void NormalizeWindowsPath(std::string &s) {
- for (char &c : s) {
-if (c == '/')
- c = '\\';
-else
- c = std::tolower(static_cast(c));
- }
-}
-
-bool IsSystemDLL(const FileSpec &spec) {
- if (!spec)
-return false;
-
- static const std::string windows_prefix = []() {
-std::string prefix;
-wchar_t buf[MAX_PATH];
-UINT len = ::GetWindowsDirectoryW(buf, MAX_PATH);
-if (len == 0 || len >= MAX_PATH)
- return prefix;
-llvm::convertWideToUTF8(std::wstring_view(buf, len), prefix);
-NormalizeWindowsPath(prefix);
-if (!prefix.empty() && prefix.back() != '\\')
- prefix += '\\';
-return prefix;
- }();
-
- if (windows_prefix.empty())
-return false;
-
- std::string path = spec.GetPath();
- NormalizeWindowsPath(path);
- return llvm::StringRef(path).starts_with(windows_prefix);
-}
-
-} // namespace
-
NativeProcessWindows::NativeProcessWindows(ProcessLaunchInfo &launch_info,
NativeDelegate &delegate,
llvm::Error &E)
@@ -635,9 +597,8 @@ NativeProcessWindows::HandleBreakpointException(const
ExceptionRecord &record) {
return ExceptionResult::BreakInDebugger;
}
- // Any remaining STATUS_BREAKPOINT is a breakpoint instruction in the
- // program's own code (e.g. `__debugbreak()` or `__builtin_debugtrap()`).
- // Stop the debugger and let the user decide what to do.
+ // Our own DebugBreakProcess() injection, used to implement
+ // Halt()/Interrupt().
if (m_pending_halt) {
LLDB_LOG(log,
"DebugBreakProcess injection treated as Halt SIGSTOP for tid "
@@ -664,6 +625,14 @@ NativeProcessWindows::HandleBreakpointException(const
ExceptionRecord &record) {
return ExceptionResult::BreakInDebugger;
}
+ if (IsSystemModuleAddress(exception_addr)) {
+LLDB_LOG(log,
+ "Ignoring loader/OS breakpoint at address {0:x} in a system "
+ "module.",
+ exception_addr);
+return ExceptionResult::MaskException;
+ }
+
std::string desc = formatv("Exception {0:x8} encountered at address {1:x8}",
record.GetExceptionValue(), exception_addr)
.str();
@@ -776,7 +745,7 @@ DllEventAction NativeProcessWindows::OnLoadDll(const
ModuleSpec &module_spec,
return DllEventAction::ContinueDebugLoop;
// Can't resolve a breakpoint in a system DLL.
- if (!resolved || IsSystemDLL(resolved))
+ if (!resolved || ProcessDebugger::IsSystemDLL(resolved))
return DllEventAction::ContinueDebugLoop;
NativeThreadWindows *loader_thread = GetThreadByID(thread_id);
@@ -819,7 +788,7 @@ DllEventAction
NativeProcessWindows::OnUnloadDll(lldb::addr_t module_addr,
if (!m_initial_stop_seen || !m_client_supports_libraries_read)
return DllEventAction::ContinueDebugLoop;
- if (!unloaded_spec || IsSystemDLL(unloaded_spec))
+ if (!unloaded_spec || ProcessDebugger::IsSystemDLL(unloaded_spec))
return DllEventAction::ContinueDebugLoop;
NativeThreadWindows *unloader_thread = GetThreadByID(thread_id);
diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
b/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
index 63fc20f36b07b..a4322c3d3f536 100644
--- a/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
@@ -19,6 +19,7 @@
#include "lldb/Host/ProcessLaunchInfo.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Process.h"
+#include "lldb/Utility/FileSpec.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Error.h"
@@ -26,9 +27,77 @@
#include "ExceptionRecord.h"
#include "ProcessWindowsLog.h"
+#include
+#include
+#include
+
using namespace lldb;
using namespace lldb_private;
+static void NormalizeWindowsPath(std::string &s) {
+ for (char &c : s) {
+if (c == '/')
[Lldb-commits] [lldb] [lldb][Windows] ignore loader breakpoints in system modules (PR #208233)
https://github.com/charles-zablit edited https://github.com/llvm/llvm-project/pull/208233 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][Windows] ignore loader breakpoints in system modules (PR #208233)
https://github.com/charles-zablit updated
https://github.com/llvm/llvm-project/pull/208233
>From d6abb3698fd1419ec5c89df61a9243cf6fcc0772 Mon Sep 17 00:00:00 2001
From: Charles Zablit
Date: Wed, 8 Jul 2026 15:46:39 +0100
Subject: [PATCH 1/4] [lldb][Windows] ignore loader breakpoints in system
modules
---
.../Windows/Common/NativeProcessWindows.cpp | 55 ---
.../Windows/Common/ProcessDebugger.cpp| 69 +++
.../Process/Windows/Common/ProcessDebugger.h | 5 ++
.../Process/Windows/Common/ProcessWindows.cpp | 16 -
4 files changed, 101 insertions(+), 44 deletions(-)
diff --git
a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
index ada92894efc47..f1de697c34b67 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
@@ -50,44 +50,6 @@ using namespace llvm;
namespace lldb_private {
-namespace {
-
-void NormalizeWindowsPath(std::string &s) {
- for (char &c : s) {
-if (c == '/')
- c = '\\';
-else
- c = std::tolower(static_cast(c));
- }
-}
-
-bool IsSystemDLL(const FileSpec &spec) {
- if (!spec)
-return false;
-
- static const std::string windows_prefix = []() {
-std::string prefix;
-wchar_t buf[MAX_PATH];
-UINT len = ::GetWindowsDirectoryW(buf, MAX_PATH);
-if (len == 0 || len >= MAX_PATH)
- return prefix;
-llvm::convertWideToUTF8(std::wstring_view(buf, len), prefix);
-NormalizeWindowsPath(prefix);
-if (!prefix.empty() && prefix.back() != '\\')
- prefix += '\\';
-return prefix;
- }();
-
- if (windows_prefix.empty())
-return false;
-
- std::string path = spec.GetPath();
- NormalizeWindowsPath(path);
- return llvm::StringRef(path).starts_with(windows_prefix);
-}
-
-} // namespace
-
NativeProcessWindows::NativeProcessWindows(ProcessLaunchInfo &launch_info,
NativeDelegate &delegate,
llvm::Error &E)
@@ -635,9 +597,8 @@ NativeProcessWindows::HandleBreakpointException(const
ExceptionRecord &record) {
return ExceptionResult::BreakInDebugger;
}
- // Any remaining STATUS_BREAKPOINT is a breakpoint instruction in the
- // program's own code (e.g. `__debugbreak()` or `__builtin_debugtrap()`).
- // Stop the debugger and let the user decide what to do.
+ // Our own DebugBreakProcess() injection, used to implement
+ // Halt()/Interrupt().
if (m_pending_halt) {
LLDB_LOG(log,
"DebugBreakProcess injection treated as Halt SIGSTOP for tid "
@@ -664,6 +625,14 @@ NativeProcessWindows::HandleBreakpointException(const
ExceptionRecord &record) {
return ExceptionResult::BreakInDebugger;
}
+ if (IsSystemModuleAddress(exception_addr)) {
+LLDB_LOG(log,
+ "Ignoring loader/OS breakpoint at address {0:x} in a system "
+ "module.",
+ exception_addr);
+return ExceptionResult::MaskException;
+ }
+
std::string desc = formatv("Exception {0:x8} encountered at address {1:x8}",
record.GetExceptionValue(), exception_addr)
.str();
@@ -776,7 +745,7 @@ DllEventAction NativeProcessWindows::OnLoadDll(const
ModuleSpec &module_spec,
return DllEventAction::ContinueDebugLoop;
// Can't resolve a breakpoint in a system DLL.
- if (!resolved || IsSystemDLL(resolved))
+ if (!resolved || ProcessDebugger::IsSystemDLL(resolved))
return DllEventAction::ContinueDebugLoop;
NativeThreadWindows *loader_thread = GetThreadByID(thread_id);
@@ -819,7 +788,7 @@ DllEventAction
NativeProcessWindows::OnUnloadDll(lldb::addr_t module_addr,
if (!m_initial_stop_seen || !m_client_supports_libraries_read)
return DllEventAction::ContinueDebugLoop;
- if (!unloaded_spec || IsSystemDLL(unloaded_spec))
+ if (!unloaded_spec || ProcessDebugger::IsSystemDLL(unloaded_spec))
return DllEventAction::ContinueDebugLoop;
NativeThreadWindows *unloader_thread = GetThreadByID(thread_id);
diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
b/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
index 63fc20f36b07b..a4322c3d3f536 100644
--- a/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
@@ -19,6 +19,7 @@
#include "lldb/Host/ProcessLaunchInfo.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Process.h"
+#include "lldb/Utility/FileSpec.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Error.h"
@@ -26,9 +27,77 @@
#include "ExceptionRecord.h"
#include "ProcessWindowsLog.h"
+#include
+#include
+#include
+
using namespace lldb;
using namespace lldb_private;
+static void NormalizeWindowsPath(std::string &s) {
+ for (char &c : s) {
+if (c == '/')
[Lldb-commits] [lldb] [lldb][Windows] ignore loader breakpoints in system modules (PR #208233)
github-actions[bot] wrote: # :window: Windows x64 Test Results * 33344 tests passed * 902 tests skipped * 3 tests failed ## Failed Tests (click on a test name to see its output) ### lldb-api lldb-api.commands/expression/expr-in-syscall/TestExpressionInSyscall.py ``` Script: -- C:/Python312/python.exe C:/_work/llvm-project/llvm-project/lldb\test\API\dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=C:/_work/llvm-project/llvm-project/build/./lib --env LLVM_INCLUDE_DIR=C:/_work/llvm-project/llvm-project/build/include --env LLVM_TOOLS_DIR=C:/_work/llvm-project/llvm-project/build/./bin --triple x86_64-pc-windows-msvc --build-dir C:/_work/llvm-project/llvm-project/build/lldb-test-build --lldb-module-cache-dir C:/_work/llvm-project/llvm-project/build/lldb-test-build/module-cache-lldb\lldb-api --clang-module-cache-dir C:/_work/llvm-project/llvm-project/build/lldb-test-build/module-cache-clang\lldb-api --executable C:/_work/llvm-project/llvm-project/build/./bin/lldb.exe --lldb-python-dir C:\_work\llvm-project\llvm-project\build\Lib\site-packages --compiler C:/_work/llvm-project/llvm-project/build/./bin/clang.exe --dsymutil C:/_work/llvm-project/llvm-project/build/./bin/dsymutil.exe --make C:/ProgramData/chocolatey/bin/make.exe --llvm-tools-dir C:/_work/llvm-project/llvm-project/build/./bin --lldb-obj-root C:/_work/llvm-project/llvm-project/build/tools/lldb --lldb-libs-dir C:/_work/llvm-project/llvm-project/build/./lib --cmake-build-type Release --env LLDB_LAUNCH_FLAG_USE_PIPES=1 C:\_work\llvm-project\llvm-project\lldb\test\API\commands\expression\expr-in-syscall -p TestExpressionInSyscall.py -- Exit Code: 1 Command Output (stdout): -- Skipping the following test categories: libc++, libstdcxx, dwo, dsym, gmodules, debugserver, objc, fork, pexpect -- Command Output (stderr): -- UNSUPPORTED: LLDB (C:\_work\llvm-project\llvm-project\build\bin\clang.exe-x86_64) :: test_setpgid_dsym (TestExpressionInSyscall.ExprSyscallTestCase.test_setpgid_dsym) (test case does not fall in any category of interest for this run) FAIL: LLDB (C:\_work\llvm-project\llvm-project\build\bin\clang.exe-x86_64) :: test_setpgid_dwarf (TestExpressionInSyscall.ExprSyscallTestCase.test_setpgid_dwarf) Log Files: - C:\_work\llvm-project\llvm-project\build\lldb-test-build\commands\expression\expr-in-syscall\TestExpressionInSyscall\Failure_test_setpgid_dwarf.log UNSUPPORTED: LLDB (C:\_work\llvm-project\llvm-project\build\bin\clang.exe-x86_64) :: test_setpgid_dwo (TestExpressionInSyscall.ExprSyscallTestCase.test_setpgid_dwo) (test case does not fall in any category of interest for this run) == FAIL: test_setpgid_dwarf (TestExpressionInSyscall.ExprSyscallTestCase.test_setpgid_dwarf) -- Traceback (most recent call last): File "C:\_work\llvm-project\llvm-project\lldb\packages\Python\lldbsuite\test\lldbtest.py", line 2186, in test_method return attrvalue(self) ^^^ File "C:\_work\llvm-project\llvm-project\lldb\test\API\commands\expression\expr-in-syscall\TestExpressionInSyscall.py", line 57, in test_setpgid self.assertEqual(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED) AssertionError: 6 != 5 : Process status should be stopped Config=x86_64-C:\_work\llvm-project\llvm-project\build\bin\clang.exe -- Ran 3 tests in 7.998s FAILED (failures=1, skipped=2) -- ``` lldb-api.commands/expression/no-deadlock/TestExprDoesntBlock.py ``` Script: -- C:/Python312/python.exe C:/_work/llvm-project/llvm-project/lldb\test\API\dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=C:/_work/llvm-project/llvm-project/build/./lib --env LLVM_INCLUDE_DIR=C:/_work/llvm-project/llvm-project/build/include --env LLVM_TOOLS_DIR=C:/_work/llvm-project/llvm-project/build/./bin --triple x86_64-pc-windows-msvc --build-dir C:/_work/llvm-project/llvm-project/build/lldb-test-build --lldb-module-cache-dir C:/_work/llvm-project/llvm-project/build/lldb-test-build/module-cache-lldb\lldb-api --clang-module-cache-dir C:/_work/llvm-project/llvm-project/build/lldb-test-build/module-cache-clang\lldb-api --executable C:/_work/llvm-project/llvm-project/build/./bin/lldb.exe --lldb-python-dir C:\_work\llvm-project\llvm-project\build\Lib\site-packages --compiler C:/_work/llvm-project/llvm-project/build/./bin/clang.exe --dsymutil C:/_work/llvm-project/llvm-project/build/./bin/dsymutil.exe --make C:/ProgramData/chocolatey/bin/make.exe --llvm-tools-dir C:/_work/llvm-project/llvm-project/build/./bin --lldb-obj-root C:/_work/llvm-project/llvm-project/build/tools/lldb --lldb-libs-dir C:/_work/llvm-project/llvm-project/build/./lib --cmake-build-type Release --env LLDB_LAUNCH_FLAG_USE_PIPES=1 C:\_work\llvm-project\llvm-project\lldb\test\API\commands\expression\no-deadlock -p TestExp
[Lldb-commits] [lldb] [lldb][Windows] ignore loader breakpoints in system modules (PR #208233)
charles-zablit wrote: > I'll read this properly tomorrow, but - > > > This is because ntdll executes an int3 breakpoint during process > > initialization when a debugger is attached. > > Do you know why it does this, is it to give the debugger a chance to set > itself up? > > If that is the case I'm curious what sorts of things that might be, > considering that we apparently haven't needed it so far. It's indeed to give the debugger a chance to set itself up, and we do use it: in `integratedTerminal` mode we start the debuggee _paused_ and then we attach to it. This produces 2 breaks: 1. an attach break 2. the loader's debugger break (this is the one that shows up unexpectedly) A regular launch (the debuggee spawns attached to the process) only has the second break. https://github.com/llvm/llvm-project/pull/208233 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][Windows] ignore loader breakpoints in system modules (PR #208233)
https://github.com/charles-zablit updated
https://github.com/llvm/llvm-project/pull/208233
>From d6abb3698fd1419ec5c89df61a9243cf6fcc0772 Mon Sep 17 00:00:00 2001
From: Charles Zablit
Date: Wed, 8 Jul 2026 15:46:39 +0100
Subject: [PATCH 1/3] [lldb][Windows] ignore loader breakpoints in system
modules
---
.../Windows/Common/NativeProcessWindows.cpp | 55 ---
.../Windows/Common/ProcessDebugger.cpp| 69 +++
.../Process/Windows/Common/ProcessDebugger.h | 5 ++
.../Process/Windows/Common/ProcessWindows.cpp | 16 -
4 files changed, 101 insertions(+), 44 deletions(-)
diff --git
a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
index ada92894efc47..f1de697c34b67 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
@@ -50,44 +50,6 @@ using namespace llvm;
namespace lldb_private {
-namespace {
-
-void NormalizeWindowsPath(std::string &s) {
- for (char &c : s) {
-if (c == '/')
- c = '\\';
-else
- c = std::tolower(static_cast(c));
- }
-}
-
-bool IsSystemDLL(const FileSpec &spec) {
- if (!spec)
-return false;
-
- static const std::string windows_prefix = []() {
-std::string prefix;
-wchar_t buf[MAX_PATH];
-UINT len = ::GetWindowsDirectoryW(buf, MAX_PATH);
-if (len == 0 || len >= MAX_PATH)
- return prefix;
-llvm::convertWideToUTF8(std::wstring_view(buf, len), prefix);
-NormalizeWindowsPath(prefix);
-if (!prefix.empty() && prefix.back() != '\\')
- prefix += '\\';
-return prefix;
- }();
-
- if (windows_prefix.empty())
-return false;
-
- std::string path = spec.GetPath();
- NormalizeWindowsPath(path);
- return llvm::StringRef(path).starts_with(windows_prefix);
-}
-
-} // namespace
-
NativeProcessWindows::NativeProcessWindows(ProcessLaunchInfo &launch_info,
NativeDelegate &delegate,
llvm::Error &E)
@@ -635,9 +597,8 @@ NativeProcessWindows::HandleBreakpointException(const
ExceptionRecord &record) {
return ExceptionResult::BreakInDebugger;
}
- // Any remaining STATUS_BREAKPOINT is a breakpoint instruction in the
- // program's own code (e.g. `__debugbreak()` or `__builtin_debugtrap()`).
- // Stop the debugger and let the user decide what to do.
+ // Our own DebugBreakProcess() injection, used to implement
+ // Halt()/Interrupt().
if (m_pending_halt) {
LLDB_LOG(log,
"DebugBreakProcess injection treated as Halt SIGSTOP for tid "
@@ -664,6 +625,14 @@ NativeProcessWindows::HandleBreakpointException(const
ExceptionRecord &record) {
return ExceptionResult::BreakInDebugger;
}
+ if (IsSystemModuleAddress(exception_addr)) {
+LLDB_LOG(log,
+ "Ignoring loader/OS breakpoint at address {0:x} in a system "
+ "module.",
+ exception_addr);
+return ExceptionResult::MaskException;
+ }
+
std::string desc = formatv("Exception {0:x8} encountered at address {1:x8}",
record.GetExceptionValue(), exception_addr)
.str();
@@ -776,7 +745,7 @@ DllEventAction NativeProcessWindows::OnLoadDll(const
ModuleSpec &module_spec,
return DllEventAction::ContinueDebugLoop;
// Can't resolve a breakpoint in a system DLL.
- if (!resolved || IsSystemDLL(resolved))
+ if (!resolved || ProcessDebugger::IsSystemDLL(resolved))
return DllEventAction::ContinueDebugLoop;
NativeThreadWindows *loader_thread = GetThreadByID(thread_id);
@@ -819,7 +788,7 @@ DllEventAction
NativeProcessWindows::OnUnloadDll(lldb::addr_t module_addr,
if (!m_initial_stop_seen || !m_client_supports_libraries_read)
return DllEventAction::ContinueDebugLoop;
- if (!unloaded_spec || IsSystemDLL(unloaded_spec))
+ if (!unloaded_spec || ProcessDebugger::IsSystemDLL(unloaded_spec))
return DllEventAction::ContinueDebugLoop;
NativeThreadWindows *unloader_thread = GetThreadByID(thread_id);
diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
b/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
index 63fc20f36b07b..a4322c3d3f536 100644
--- a/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
@@ -19,6 +19,7 @@
#include "lldb/Host/ProcessLaunchInfo.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Process.h"
+#include "lldb/Utility/FileSpec.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Error.h"
@@ -26,9 +27,77 @@
#include "ExceptionRecord.h"
#include "ProcessWindowsLog.h"
+#include
+#include
+#include
+
using namespace lldb;
using namespace lldb_private;
+static void NormalizeWindowsPath(std::string &s) {
+ for (char &c : s) {
+if (c == '/')
[Lldb-commits] [lldb] [lldb][Windows] ignore loader breakpoints in system modules (PR #208233)
DavidSpickett wrote: I'll read this properly tomorrow, but - > This is because ntdll executes an int3 breakpoint during process > initialization when a debugger is attached. Do you know why it does this, is it to give the debugger a chance to set itself up? If that is the case I'm curious what sorts of things that might be, considering that we apparently haven't needed it so far. https://github.com/llvm/llvm-project/pull/208233 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][Windows] ignore loader breakpoints in system modules (PR #208233)
llvmorg-github-actions[bot] wrote:
@llvm/pr-subscribers-lldb
Author: Charles Zablit (charles-zablit)
Changes
Currently, when debugging a program with `lldb-dap` on Windows and the
`integratedTerminal` option, lldb-dap immediatly stops with an `0x8003`
Exception. This is because `ntdll` executes an `int3` breakpoint during process
initialization when a debugger is attached.
This patch makes lldb and lldb-server ignore `int3` breakpoints are in system
modules.
Fixes https://github.com/llvm/llvm-project/issues/198763
---
Full diff: https://github.com/llvm/llvm-project/pull/208233.diff
5 Files Affected:
- (modified)
lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp (+12-43)
- (modified) lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
(+69)
- (modified) lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.h (+5)
- (modified) lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
(+15-1)
- (modified)
lldb/test/API/tools/lldb-dap/runInTerminal/TestDAP_runInTerminal.py (-1)
``diff
diff --git
a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
index ada92894efc47..f1de697c34b67 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
@@ -50,44 +50,6 @@ using namespace llvm;
namespace lldb_private {
-namespace {
-
-void NormalizeWindowsPath(std::string &s) {
- for (char &c : s) {
-if (c == '/')
- c = '\\';
-else
- c = std::tolower(static_cast(c));
- }
-}
-
-bool IsSystemDLL(const FileSpec &spec) {
- if (!spec)
-return false;
-
- static const std::string windows_prefix = []() {
-std::string prefix;
-wchar_t buf[MAX_PATH];
-UINT len = ::GetWindowsDirectoryW(buf, MAX_PATH);
-if (len == 0 || len >= MAX_PATH)
- return prefix;
-llvm::convertWideToUTF8(std::wstring_view(buf, len), prefix);
-NormalizeWindowsPath(prefix);
-if (!prefix.empty() && prefix.back() != '\\')
- prefix += '\\';
-return prefix;
- }();
-
- if (windows_prefix.empty())
-return false;
-
- std::string path = spec.GetPath();
- NormalizeWindowsPath(path);
- return llvm::StringRef(path).starts_with(windows_prefix);
-}
-
-} // namespace
-
NativeProcessWindows::NativeProcessWindows(ProcessLaunchInfo &launch_info,
NativeDelegate &delegate,
llvm::Error &E)
@@ -635,9 +597,8 @@ NativeProcessWindows::HandleBreakpointException(const
ExceptionRecord &record) {
return ExceptionResult::BreakInDebugger;
}
- // Any remaining STATUS_BREAKPOINT is a breakpoint instruction in the
- // program's own code (e.g. `__debugbreak()` or `__builtin_debugtrap()`).
- // Stop the debugger and let the user decide what to do.
+ // Our own DebugBreakProcess() injection, used to implement
+ // Halt()/Interrupt().
if (m_pending_halt) {
LLDB_LOG(log,
"DebugBreakProcess injection treated as Halt SIGSTOP for tid "
@@ -664,6 +625,14 @@ NativeProcessWindows::HandleBreakpointException(const
ExceptionRecord &record) {
return ExceptionResult::BreakInDebugger;
}
+ if (IsSystemModuleAddress(exception_addr)) {
+LLDB_LOG(log,
+ "Ignoring loader/OS breakpoint at address {0:x} in a system "
+ "module.",
+ exception_addr);
+return ExceptionResult::MaskException;
+ }
+
std::string desc = formatv("Exception {0:x8} encountered at address {1:x8}",
record.GetExceptionValue(), exception_addr)
.str();
@@ -776,7 +745,7 @@ DllEventAction NativeProcessWindows::OnLoadDll(const
ModuleSpec &module_spec,
return DllEventAction::ContinueDebugLoop;
// Can't resolve a breakpoint in a system DLL.
- if (!resolved || IsSystemDLL(resolved))
+ if (!resolved || ProcessDebugger::IsSystemDLL(resolved))
return DllEventAction::ContinueDebugLoop;
NativeThreadWindows *loader_thread = GetThreadByID(thread_id);
@@ -819,7 +788,7 @@ DllEventAction
NativeProcessWindows::OnUnloadDll(lldb::addr_t module_addr,
if (!m_initial_stop_seen || !m_client_supports_libraries_read)
return DllEventAction::ContinueDebugLoop;
- if (!unloaded_spec || IsSystemDLL(unloaded_spec))
+ if (!unloaded_spec || ProcessDebugger::IsSystemDLL(unloaded_spec))
return DllEventAction::ContinueDebugLoop;
NativeThreadWindows *unloader_thread = GetThreadByID(thread_id);
diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
b/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
index 63fc20f36b07b..a4322c3d3f536 100644
--- a/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
@@ -19,6 +19,7 @@
#include "lldb/Host/ProcessLaunchInfo.
[Lldb-commits] [lldb] [lldb][Windows] ignore loader breakpoints in system modules (PR #208233)
https://github.com/charles-zablit created
https://github.com/llvm/llvm-project/pull/208233
Currently, when debugging a program with `lldb-dap` on Windows and the
`integratedTerminal` option, lldb-dap immediatly stops with an `0x8003`
Exception. This is because `ntdll` executes an `int3` breakpoint during process
initialization when a debugger is attached.
This patch makes lldb and lldb-server ignore `int3` breakpoints are in system
modules.
Fixes https://github.com/llvm/llvm-project/issues/198763
>From d6abb3698fd1419ec5c89df61a9243cf6fcc0772 Mon Sep 17 00:00:00 2001
From: Charles Zablit
Date: Wed, 8 Jul 2026 15:46:39 +0100
Subject: [PATCH 1/2] [lldb][Windows] ignore loader breakpoints in system
modules
---
.../Windows/Common/NativeProcessWindows.cpp | 55 ---
.../Windows/Common/ProcessDebugger.cpp| 69 +++
.../Process/Windows/Common/ProcessDebugger.h | 5 ++
.../Process/Windows/Common/ProcessWindows.cpp | 16 -
4 files changed, 101 insertions(+), 44 deletions(-)
diff --git
a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
index ada92894efc47..f1de697c34b67 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
@@ -50,44 +50,6 @@ using namespace llvm;
namespace lldb_private {
-namespace {
-
-void NormalizeWindowsPath(std::string &s) {
- for (char &c : s) {
-if (c == '/')
- c = '\\';
-else
- c = std::tolower(static_cast(c));
- }
-}
-
-bool IsSystemDLL(const FileSpec &spec) {
- if (!spec)
-return false;
-
- static const std::string windows_prefix = []() {
-std::string prefix;
-wchar_t buf[MAX_PATH];
-UINT len = ::GetWindowsDirectoryW(buf, MAX_PATH);
-if (len == 0 || len >= MAX_PATH)
- return prefix;
-llvm::convertWideToUTF8(std::wstring_view(buf, len), prefix);
-NormalizeWindowsPath(prefix);
-if (!prefix.empty() && prefix.back() != '\\')
- prefix += '\\';
-return prefix;
- }();
-
- if (windows_prefix.empty())
-return false;
-
- std::string path = spec.GetPath();
- NormalizeWindowsPath(path);
- return llvm::StringRef(path).starts_with(windows_prefix);
-}
-
-} // namespace
-
NativeProcessWindows::NativeProcessWindows(ProcessLaunchInfo &launch_info,
NativeDelegate &delegate,
llvm::Error &E)
@@ -635,9 +597,8 @@ NativeProcessWindows::HandleBreakpointException(const
ExceptionRecord &record) {
return ExceptionResult::BreakInDebugger;
}
- // Any remaining STATUS_BREAKPOINT is a breakpoint instruction in the
- // program's own code (e.g. `__debugbreak()` or `__builtin_debugtrap()`).
- // Stop the debugger and let the user decide what to do.
+ // Our own DebugBreakProcess() injection, used to implement
+ // Halt()/Interrupt().
if (m_pending_halt) {
LLDB_LOG(log,
"DebugBreakProcess injection treated as Halt SIGSTOP for tid "
@@ -664,6 +625,14 @@ NativeProcessWindows::HandleBreakpointException(const
ExceptionRecord &record) {
return ExceptionResult::BreakInDebugger;
}
+ if (IsSystemModuleAddress(exception_addr)) {
+LLDB_LOG(log,
+ "Ignoring loader/OS breakpoint at address {0:x} in a system "
+ "module.",
+ exception_addr);
+return ExceptionResult::MaskException;
+ }
+
std::string desc = formatv("Exception {0:x8} encountered at address {1:x8}",
record.GetExceptionValue(), exception_addr)
.str();
@@ -776,7 +745,7 @@ DllEventAction NativeProcessWindows::OnLoadDll(const
ModuleSpec &module_spec,
return DllEventAction::ContinueDebugLoop;
// Can't resolve a breakpoint in a system DLL.
- if (!resolved || IsSystemDLL(resolved))
+ if (!resolved || ProcessDebugger::IsSystemDLL(resolved))
return DllEventAction::ContinueDebugLoop;
NativeThreadWindows *loader_thread = GetThreadByID(thread_id);
@@ -819,7 +788,7 @@ DllEventAction
NativeProcessWindows::OnUnloadDll(lldb::addr_t module_addr,
if (!m_initial_stop_seen || !m_client_supports_libraries_read)
return DllEventAction::ContinueDebugLoop;
- if (!unloaded_spec || IsSystemDLL(unloaded_spec))
+ if (!unloaded_spec || ProcessDebugger::IsSystemDLL(unloaded_spec))
return DllEventAction::ContinueDebugLoop;
NativeThreadWindows *unloader_thread = GetThreadByID(thread_id);
diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
b/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
index 63fc20f36b07b..a4322c3d3f536 100644
--- a/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/ProcessDebugger.cpp
@@ -19,6 +19,7 @@
#include "lldb/Host/ProcessLaunchInfo.h"
#include "lldb/Target/MemoryReg
