[Lldb-commits] [lldb] [lldb][windows] add attach by name capability (PR #173015)
Charles Zablit via lldb-commits
lldb-commits at lists.llvm.org
Fri Dec 19 07:13:53 PST 2025
https://github.com/charles-zablit created https://github.com/llvm/llvm-project/pull/173015
This patch adds the _attach by name_ feature to lldb/lldb-dap on Windows.
Using the [`CreateToolhelp32Snapshot `](https://learn.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-createtoolhelp32snapshot) API and by iterating over the processes in the snapshot, lldb returns the pid of the first match, if any.
This implementation is based on: https://learn.microsoft.com/en-us/windows/win32/toolhelp/taking-a-snapshot-and-viewing-processes
>From 40f3dc018772d1bf58319f1df959f5c75c70c863 Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Fri, 19 Dec 2025 15:10:36 +0000
Subject: [PATCH] [lldb][windows] add attach by name capability
---
.../Process/Windows/Common/ProcessWindows.cpp | 52 +++++++++++++++++++
.../Process/Windows/Common/ProcessWindows.h | 19 +++++++
.../tools/lldb-dap/attach/TestDAP_attach.py | 1 -
3 files changed, 71 insertions(+), 1 deletion(-)
diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
index 127dd0f59e9ae..19b895cda77d9 100644
--- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
@@ -10,6 +10,7 @@
// Windows includes
#include "lldb/Host/windows/windows.h"
+#include <TlHelp32.h>
#include <psapi.h>
#include "lldb/Breakpoint/Watchpoint.h"
@@ -35,6 +36,7 @@
#include "lldb/Utility/Log.h"
#include "lldb/Utility/State.h"
+#include "llvm/ADT/ScopeExit.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Threading.h"
@@ -227,6 +229,56 @@ ProcessWindows::DoAttachToProcessWithID(lldb::pid_t pid,
return error;
}
+Status ProcessWindows::DoAttachToProcessWithName(
+ const char *process_name, const ProcessAttachInfo &attach_info) {
+ Status error;
+ Clear();
+
+ if (!process_name || process_name[0] == '\0') {
+ error = Status::FromErrorString("Invalid process name");
+ return error;
+ }
+
+ lldb::pid_t pid = FindProcessByName(process_name, error);
+
+ if (pid == LLDB_INVALID_PROCESS_ID) {
+ error = Status::FromErrorStringWithFormatv("Unable to find process '%s'",
+ process_name);
+ return error;
+ }
+
+ return DoAttachToProcessWithID(pid, attach_info);
+}
+
+lldb::pid_t ProcessWindows::FindProcessByName(const char *process_name,
+ Status &error) {
+ HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ if (hProcessSnap == INVALID_HANDLE_VALUE) {
+ error = Status(GetLastError(), eErrorTypeWin32);
+ return LLDB_INVALID_PROCESS_ID;
+ }
+ auto cleanup = llvm::make_scope_exit([&] { CloseHandle(hProcessSnap); });
+
+ llvm::StringRef process_filename = llvm::sys::path::filename(process_name);
+
+ PROCESSENTRY32W pe32;
+ pe32.dwSize = sizeof(PROCESSENTRY32W);
+ if (!Process32FirstW(hProcessSnap, &pe32)) {
+ error = Status(GetLastError(), eErrorTypeWin32);
+ return LLDB_INVALID_PROCESS_ID;
+ }
+
+ do {
+ std::string exe_name;
+ llvm::convertWideToUTF8(pe32.szExeFile, exe_name);
+
+ if (exe_name == process_filename)
+ return pe32.th32ProcessID;
+ } while (Process32NextW(hProcessSnap, &pe32));
+
+ return LLDB_INVALID_PROCESS_ID;
+}
+
Status ProcessWindows::DoResume(RunDirection direction) {
Log *log = GetLog(WindowsLog::Process);
llvm::sys::ScopedLock lock(m_mutex);
diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h
index 33e4de6b85932..be861db31ba36 100644
--- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h
+++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h
@@ -49,6 +49,9 @@ class ProcessWindows : public Process, public ProcessDebugger {
Status DoAttachToProcessWithID(
lldb::pid_t pid,
const lldb_private::ProcessAttachInfo &attach_info) override;
+ Status
+ DoAttachToProcessWithName(const char *process_name,
+ const ProcessAttachInfo &attach_info) override;
Status DoResume(lldb::RunDirection direction) override;
Status DoDestroy() override;
Status DoHalt(bool &caused_stop) override;
@@ -101,6 +104,22 @@ class ProcessWindows : public Process, public ProcessDebugger {
void
SetPseudoConsoleHandle(const std::shared_ptr<PseudoConsole> &pty) override;
+ /// Finds the pid matching the process_name.
+ ///
+ /// If there are multiple processes with the same name, this method will
+ /// return the first one.
+ ///
+ /// \param[in] process_name
+ /// The name of the process to find.
+ ///
+ /// \param[out] error
+ /// An error that indicates the success or failure of the search.
+ ///
+ /// \return
+ /// Returns the pid of the process if a match was found. Returns \code
+ /// LLDB_INVALID_PROCESS otherwise.
+ lldb::pid_t FindProcessByName(const char *process_name, Status &error);
+
protected:
ProcessWindows(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp);
diff --git a/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py b/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py
index d9acd0a4cae01..d6287397a93b0 100644
--- a/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py
+++ b/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py
@@ -59,7 +59,6 @@ def test_by_name(self):
self.attach(program=program)
self.continue_and_verify_pid()
- @expectedFailureWindows
def test_by_name_waitFor(self):
"""
Tests waiting for, and attaching to a process by process name that
More information about the lldb-commits
mailing list