[Lldb-commits] [lldb] [llvm] [DO NOT MERGE YET] attempt to fix check-lldb in PR CI (PR #198630)

Charles Zablit via lldb-commits lldb-commits at lists.llvm.org
Fri May 29 06:14:01 PDT 2026


https://github.com/charles-zablit updated https://github.com/llvm/llvm-project/pull/198630

>From daecf7dba191efd5f41fd1ee16a82a9e5bec58cc Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Wed, 20 May 2026 16:53:45 +0100
Subject: [PATCH 1/4] to revert

---
 .github/workflows/premerge.yaml                   | 15 +++++++++++----
 .../functionalities/load_unload/TestLoadUnload.py |  2 +-
 2 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/.github/workflows/premerge.yaml b/.github/workflows/premerge.yaml
index d506e631e2f21..8f68d57067762 100644
--- a/.github/workflows/premerge.yaml
+++ b/.github/workflows/premerge.yaml
@@ -157,10 +157,17 @@ jobs:
           echo "Building runtimes: ${runtimes_to_build}"
           echo "Running runtimes checks targets: ${runtimes_check_targets}"
 
-          echo "windows-projects=${projects_to_build}" >> $GITHUB_OUTPUT
-          echo "windows-check-targets=${project_check_targets}" >> $GITHUB_OUTPUT
-          echo "windows-runtimes=${runtimes_to_build}" >> $GITHUB_OUTPUT
-          echo "windows-runtimes-check-targets=${runtimes_check_targets}" >> $GITHUB_OUTPUT
+          # DIAGNOSTIC (revert before merge): force lldb-only check-lldb on
+          # Windows so this branch's CI runs the failing test fast, without
+          # waiting on the rest of llvm/clang/lld/etc.
+          echo "windows-projects=clang;lld;lldb;llvm" >> $GITHUB_OUTPUT
+          echo "windows-check-targets=check-lldb" >> $GITHUB_OUTPUT
+          echo "windows-runtimes=" >> $GITHUB_OUTPUT
+          echo "windows-runtimes-check-targets=" >> $GITHUB_OUTPUT
+      - name: Install make (DIAGNOSTIC, will move to ci-windows Dockerfile)
+        if: ${{ steps.vars.outputs.windows-projects != '' }}
+        shell: cmd
+        run: choco install -y --no-progress make --version 4.4.1
       - name: Build and Test
         timeout-minutes: 180
         if: ${{ steps.vars.outputs.windows-projects != '' }}
diff --git a/lldb/test/API/functionalities/load_unload/TestLoadUnload.py b/lldb/test/API/functionalities/load_unload/TestLoadUnload.py
index 97ca9f84b203d..df3578db47a85 100644
--- a/lldb/test/API/functionalities/load_unload/TestLoadUnload.py
+++ b/lldb/test/API/functionalities/load_unload/TestLoadUnload.py
@@ -410,7 +410,7 @@ def run_step_over_load(self):
         oslist=["freebsd", "linux", "netbsd"],
         remote=False,
     )
-    @expectedFailureAll(oslist=["windows"], archs=["aarch64"])
+    @skipIfWindows
     def test_static_init_during_load(self):
         """Test that we can set breakpoints correctly in static initializers"""
         self.copy_shlibs_to_remote()

>From 3e12427a464b8c123bbf9c8418ad2347842b5f68 Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Thu, 28 May 2026 17:04:46 +0100
Subject: [PATCH 2/4] [lldb][windows] resolve container-layer DLL paths via
 volume enumeration

When the Windows debug API delivers LOAD_DLL_DEBUG_EVENT with hFile=NULL
(common in Windows Server Core containers for kernel32.dll, KernelBase.dll
and ucrtbase.dll), HandleLoadDllEvent falls back to GetMappedFileNameW +
ConvertNtDevicePathToDosPath. The conversion was failing in containers
because the volume backing system DLLs has no drive-letter assignment, so
walking GetLogicalDriveStringsW found no match.

* ConvertNtDevicePathToDosPath: enumerate every volume on the system via
  FindFirstVolumeW / FindNextVolumeW, look up its device name with
  QueryDosDeviceW, and resolve to the first mount point returned by
  GetVolumePathNamesForVolumeNameW. If no mount point exists, fall back
  to the volume's GUID path (\\?\Volume{GUID}\...), which Win32 APIs can
  still open.

* GetFileNameByLoadAddress: use a 32K wchar_t buffer for
  GetMappedFileNameW (Windows extended path limit). The previous
  MAX_PATH+1 buffer caused len=0 with ERROR_MORE_DATA on some DLLs even
  when the actual path is well under MAX_PATH.

* GetFileNameFromImageNameField: bound ReadProcessMemory by the size of
  the committed region at name_addr (via VirtualQueryEx) to avoid
  ERROR_PARTIAL_COPY when the path is short and a greedy read would span
  into an unmapped page. Replace the strict
  wbuf[MAX_PATH] != L'\\0' / abuf[MAX_PATH] != '\\0' check with wcsnlen /
  strnlen so we don't reject valid short paths whose buffer suffix
  happens to be non-zero from inferior heap reuse.

Add LLDB_LOG calls along every branch of HandleLoadDllEvent and its
helpers (channel: windows event) so future failures can be diagnosed
without rebuilding lldb.
---
 .../Process/Windows/Common/DebuggerThread.cpp | 144 ++++++++++++++++--
 1 file changed, 129 insertions(+), 15 deletions(-)

diff --git a/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp b/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp
index 22a836f9cbed5..f78ebf13d658e 100644
--- a/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp
@@ -553,7 +553,14 @@ ConvertNtDevicePathToDosPath(llvm::ArrayRef<wchar_t> nt_path) {
     return result;
   } while (::FindNextVolumeW(vol_iter, vol_name.data(), vol_name.size()));
 
-  LLDB_LOG(log, "ConvertNtDevicePathToDosPath: no matching volume found");
+  std::wstring nt_str(nt_path.data(),
+                      ::wcsnlen(nt_path.data(), nt_path.size()));
+  std::string nt_utf8;
+  llvm::convertWideToUTF8(nt_str, nt_utf8);
+  LLDB_LOG(log,
+           "ConvertNtDevicePathToDosPath: no matching volume found for "
+           "nt_path \"{0}\"",
+           nt_utf8);
   return std::nullopt;
 }
 
@@ -586,10 +593,15 @@ static std::optional<std::string> GetFileNameFromHandleFallback(HANDLE hFile) {
 
 static std::optional<std::string> GetFileNameByLoadAddress(HANDLE hProcess,
                                                            LPVOID base_addr) {
+  Log *log = GetLog(WindowsLog::Event);
   std::array<wchar_t, MAX_PATH + 1> module_filename;
   DWORD len =
       ::GetModuleFileNameExW(hProcess, reinterpret_cast<HMODULE>(base_addr),
                              module_filename.data(), module_filename.size());
+  LLDB_LOG(log,
+           "GetFileNameByLoadAddress: GetModuleFileNameExW(base={0:x}) "
+           "len={1}, error={2}",
+           base_addr, len, ::GetLastError());
   if (len > 0 && len < module_filename.size()) {
     std::string path_utf8;
     llvm::convertWideToUTF8(std::wstring(module_filename.data(), len),
@@ -605,52 +617,141 @@ static std::optional<std::string> GetFileNameByLoadAddress(HANDLE hProcess,
         hProcess, base_addr, mapped_filename.data(), mapped_filename.size());
     if (mapped_len < mapped_filename.size())
       break;
-    if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+    if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+      LLDB_LOG(log,
+               "GetFileNameByLoadAddress: GetMappedFileNameW(base={0:x}) "
+               "failed, buffer={1}, error={2}",
+               base_addr, mapped_filename.size(), ::GetLastError());
       return std::nullopt;
+    }
     mapped_filename.resize(mapped_filename.size() * 2);
   }
+  LLDB_LOG(log,
+           "GetFileNameByLoadAddress: GetMappedFileNameW(base={0:x}) len={1}",
+           base_addr, mapped_len);
   std::optional<std::string> dos_path = ConvertNtDevicePathToDosPath(
       llvm::ArrayRef<wchar_t>(mapped_filename.data(), mapped_len + 1));
+  LLDB_LOG(log,
+           "GetFileNameByLoadAddress: ConvertNtDevicePathToDosPath -> {0}",
+           dos_path ? *dos_path : "<nullopt>");
   return dos_path;
 }
 
+// Determine how many bytes can be read at `addr` in `hProcess` before crossing
+// out of the committed memory region containing it. Returns 0 if the address
+// is not within a committed region.
+static SIZE_T BytesReadableAt(HANDLE hProcess, LPCVOID addr) {
+  MEMORY_BASIC_INFORMATION mbi{};
+  if (!::VirtualQueryEx(hProcess, addr, &mbi, sizeof(mbi)))
+    return 0;
+  if (mbi.State != MEM_COMMIT)
+    return 0;
+  uintptr_t region_end =
+      reinterpret_cast<uintptr_t>(mbi.BaseAddress) + mbi.RegionSize;
+  uintptr_t a = reinterpret_cast<uintptr_t>(addr);
+  if (a >= region_end)
+    return 0;
+  return region_end - a;
+}
+
 // Resolve the LOAD_DLL_DEBUG_INFO::lpImageName field.
 static std::optional<std::string>
 GetFileNameFromImageNameField(HANDLE hProcess,
                               const LOAD_DLL_DEBUG_INFO &info) {
-  if (info.lpImageName == nullptr)
+  Log *log = GetLog(WindowsLog::Event);
+  if (info.lpImageName == nullptr) {
+    LLDB_LOG(log, "GetFileNameFromImageNameField: lpImageName is null");
     return std::nullopt;
+  }
 
   LPVOID name_addr = nullptr;
   SIZE_T bytes_read = 0;
   if (!::ReadProcessMemory(hProcess, info.lpImageName, &name_addr,
                            sizeof(name_addr), &bytes_read) ||
-      bytes_read != sizeof(name_addr) || name_addr == nullptr)
+      bytes_read != sizeof(name_addr) || name_addr == nullptr) {
+    LLDB_LOG(log,
+             "GetFileNameFromImageNameField: ReadProcessMemory(lpImageName="
+             "{0:x}) bytes_read={1}, name_addr={2:x}, error={3}",
+             info.lpImageName, bytes_read, name_addr, ::GetLastError());
     return std::nullopt;
+  }
 
   if (info.fUnicode) {
     std::array<wchar_t, MAX_PATH + 1> wbuf{};
-    if (!::ReadProcessMemory(hProcess, name_addr, wbuf.data(),
-                             wbuf.size() * sizeof(wchar_t), &bytes_read))
+    // Bound the read by the size of the committed region at name_addr to
+    // avoid ERROR_PARTIAL_COPY when the path is short and the buffer would
+    // otherwise span into an unmapped page.
+    SIZE_T to_read =
+        std::min<SIZE_T>(wbuf.size() * sizeof(wchar_t),
+                         BytesReadableAt(hProcess, name_addr));
+    to_read &= ~SIZE_T(1); // round down to a wchar_t boundary
+    if (to_read < sizeof(wchar_t)) {
+      LLDB_LOG(log,
+               "GetFileNameFromImageNameField: no readable bytes at "
+               "name_addr={0:x}",
+               name_addr);
       return std::nullopt;
-    if (wbuf[MAX_PATH] != L'\0')
+    }
+    if (!::ReadProcessMemory(hProcess, name_addr, wbuf.data(), to_read,
+                             &bytes_read)) {
+      LLDB_LOG(log,
+               "GetFileNameFromImageNameField: ReadProcessMemory(unicode "
+               "name_addr={0:x}, to_read={1}) failed, error={2}",
+               name_addr, to_read, ::GetLastError());
       return std::nullopt;
-    std::string path_utf8;
-    llvm::convertWideToUTF8(wbuf.data(), path_utf8);
-    if (path_utf8.empty())
+    }
+    size_t max_chars = bytes_read / sizeof(wchar_t);
+    size_t wlen = ::wcsnlen(wbuf.data(), max_chars);
+    if (wlen == 0) {
+      LLDB_LOG(log, "GetFileNameFromImageNameField: unicode name is empty");
+      return std::nullopt;
+    }
+    if (wlen == max_chars) {
+      LLDB_LOG(log,
+               "GetFileNameFromImageNameField: unicode name not "
+               "null-terminated within {0} chars",
+               max_chars);
       return std::nullopt;
+    }
+    std::string path_utf8;
+    llvm::convertWideToUTF8(std::wstring(wbuf.data(), wlen), path_utf8);
+    LLDB_LOG(log, "GetFileNameFromImageNameField: unicode resolved -> {0}",
+             path_utf8);
     return path_utf8;
   }
 
   std::array<char, MAX_PATH + 1> abuf{};
-  if (!::ReadProcessMemory(hProcess, name_addr, abuf.data(), abuf.size(),
-                           &bytes_read))
+  SIZE_T to_read =
+      std::min<SIZE_T>(abuf.size(), BytesReadableAt(hProcess, name_addr));
+  if (to_read == 0) {
+    LLDB_LOG(log,
+             "GetFileNameFromImageNameField: no readable bytes at "
+             "name_addr={0:x}",
+             name_addr);
     return std::nullopt;
-  if (abuf[MAX_PATH] != '\0')
+  }
+  if (!::ReadProcessMemory(hProcess, name_addr, abuf.data(), to_read,
+                           &bytes_read)) {
+    LLDB_LOG(log,
+             "GetFileNameFromImageNameField: ReadProcessMemory(ascii "
+             "name_addr={0:x}, to_read={1}) failed, error={2}",
+             name_addr, to_read, ::GetLastError());
     return std::nullopt;
-  std::string path(abuf.data());
-  if (path.empty())
+  }
+  size_t alen = ::strnlen(abuf.data(), bytes_read);
+  if (alen == 0) {
+    LLDB_LOG(log, "GetFileNameFromImageNameField: ascii name is empty");
     return std::nullopt;
+  }
+  if (alen == bytes_read) {
+    LLDB_LOG(log,
+             "GetFileNameFromImageNameField: ascii name not null-terminated "
+             "within {0} bytes",
+             bytes_read);
+    return std::nullopt;
+  }
+  std::string path(abuf.data(), alen);
+  LLDB_LOG(log, "GetFileNameFromImageNameField: ascii resolved -> {0}", path);
   return path;
 }
 
@@ -658,6 +759,10 @@ DWORD
 DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info,
                                    DWORD thread_id) {
   Log *log = GetLog(WindowsLog::Event);
+  LLDB_LOG(log,
+           "HandleLoadDllEvent: hFile={0}, lpBaseOfDll={1:x}, "
+           "lpImageName={2:x}, fUnicode={3}",
+           info.hFile, info.lpBaseOfDll, info.lpImageName, info.fUnicode);
 
   auto on_load_dll = [&](llvm::StringRef path) {
     FileSpec file_spec(path);
@@ -684,8 +789,17 @@ DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info,
       llvm::StringRef path_str = path_str_utf8;
       path_str.consume_front("\\\\?\\");
       resolved_path = path_str.str();
+      LLDB_LOG(log,
+               "HandleLoadDllEvent: GetFinalPathNameByHandleW resolved -> {0}",
+               *resolved_path);
     } else {
+      LLDB_LOG(log,
+               "HandleLoadDllEvent: GetFinalPathNameByHandleW failed, error={0}"
+               ", trying GetFileNameFromHandleFallback",
+               ::GetLastError());
       resolved_path = GetFileNameFromHandleFallback(info.hFile);
+      LLDB_LOG(log, "HandleLoadDllEvent: GetFileNameFromHandleFallback -> {0}",
+               resolved_path ? *resolved_path : "<nullopt>");
     }
   }
 

>From 9d76017d44f695e9da09870d6dd405fc4d5a5304 Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Thu, 28 May 2026 17:05:08 +0100
Subject: [PATCH 3/4] [ci][windows] collect lldb per-test failure logs in CI
 artifacts

DIAGNOSTIC infrastructure for the kernel32 LOAD_DLL investigation.
Drop this commit before merging the lldb fix.

* utils.sh at-exit: collect Failure_*.log, *-host.log,
  ExpectedFailure_*.log and UnexpectedSuccess_*.log files from
  build/lldb-test-build.noindex/ into artifacts/lldb-test-logs/,
  preserving directory structure. Use bash globstar (`**`) for the
  recursion - PATH on the GH Actions Windows runner resolves `find` to
  C:\Windows\System32\find.exe (the DOS string-search utility), not GNU
  find, so the obvious approach silently fails. Wrap the block in
  `set +e` so a collection failure cannot skip the GitHub Actions
  reporting block, and write a self-describing artifacts/at-exit-debug.txt
  up front so the next run is debuggable even if the loop no-ops.

* premerge.yaml: clarify the lld-must-stay rationale - the lldb test
  driver links test inferiors with -fuse-ld=lld, so dropping lld breaks
  every API test that builds an inferior even though we don't run
  check-lld.
---
 .ci/utils.sh                    | 39 +++++++++++++++++++++++++++++++++
 .github/workflows/premerge.yaml |  4 +++-
 2 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/.ci/utils.sh b/.ci/utils.sh
index f14fe753415ce..5bdd9eb337c27 100644
--- a/.ci/utils.sh
+++ b/.ci/utils.sh
@@ -30,6 +30,45 @@ function at-exit {
   cp "${MONOREPO_ROOT}"/*.log artifacts/ || :
   cp "${BUILD_DIR}"/test-results.*.xml artifacts/ || :
 
+  # Collect lldb per-test session and host logs (from `--channel "lldb event"`)
+  # so we can post-mortem Windows DLL-load resolution in containers.
+  # Wrapped in `set +e ... set -e` because a failure here must not skip the
+  # GitHub Actions reporting block below.
+  set +e
+  shopt -s globstar nullglob
+  lldb_test_log_root="${BUILD_DIR}/lldb-test-build.noindex"
+  debug_log="artifacts/at-exit-debug.txt"
+  {
+    echo "=== at-exit lldb-test-logs collection ==="
+    echo "PWD: $(pwd)"
+    echo "BUILD_DIR: ${BUILD_DIR}"
+    echo "lldb_test_log_root: ${lldb_test_log_root}"
+    echo "exists: $([[ -d "${lldb_test_log_root}" ]] && echo yes || echo no)"
+  } > "${debug_log}" 2>&1
+
+  if [[ -d "${lldb_test_log_root}" ]]; then
+    mkdir -p artifacts/lldb-test-logs
+    # Use bash globstar instead of `find` because on the Windows GH Actions
+    # runner, PATH resolves `find` to C:\Windows\System32\find.exe (DOS
+    # string-search utility), which silently fails for filesystem traversal.
+    matched=0
+    for f in \
+      "${lldb_test_log_root}"/**/Failure_*.log \
+      "${lldb_test_log_root}"/**/*-host.log \
+      "${lldb_test_log_root}"/**/ExpectedFailure_*.log \
+      "${lldb_test_log_root}"/**/UnexpectedSuccess_*.log; do
+      [[ -f "${f}" ]] || continue
+      rel="${f#${lldb_test_log_root}/}"
+      mkdir -p "artifacts/lldb-test-logs/$(dirname "${rel}")" 2>/dev/null
+      cp "${f}" "artifacts/lldb-test-logs/${rel}" 2>/dev/null
+      matched=$((matched + 1))
+    done
+    echo "matched=${matched}" >> "${debug_log}"
+    echo "artifacts/lldb-test-logs file count: $(/usr/bin/find artifacts/lldb-test-logs -type f 2>/dev/null | wc -l)" >> "${debug_log}"
+  fi
+  shopt -u globstar nullglob
+  set -e
+
   # If building fails there will be no results files.
   shopt -s nullglob
 
diff --git a/.github/workflows/premerge.yaml b/.github/workflows/premerge.yaml
index 8f68d57067762..5a3b24932ef81 100644
--- a/.github/workflows/premerge.yaml
+++ b/.github/workflows/premerge.yaml
@@ -159,7 +159,9 @@ jobs:
 
           # DIAGNOSTIC (revert before merge): force lldb-only check-lldb on
           # Windows so this branch's CI runs the failing test fast, without
-          # waiting on the rest of llvm/clang/lld/etc.
+          # waiting on the rest of llvm/clang/lld/etc. lld stays in the
+          # project list because the lldb test driver links test binaries
+          # with `-fuse-ld=lld`.
           echo "windows-projects=clang;lld;lldb;llvm" >> $GITHUB_OUTPUT
           echo "windows-check-targets=check-lldb" >> $GITHUB_OUTPUT
           echo "windows-runtimes=" >> $GITHUB_OUTPUT

>From 807feaa755a026d7af59d130c8ac6aa616865206 Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Fri, 29 May 2026 14:13:39 +0100
Subject: [PATCH 4/4] Revert "[lldb][windows] resolve container-layer DLL paths
 via volume enumeration"

This reverts commit 3e12427a464b8c123bbf9c8418ad2347842b5f68.
---
 .../Process/Windows/Common/DebuggerThread.cpp | 144 ++----------------
 1 file changed, 15 insertions(+), 129 deletions(-)

diff --git a/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp b/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp
index f78ebf13d658e..22a836f9cbed5 100644
--- a/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp
@@ -553,14 +553,7 @@ ConvertNtDevicePathToDosPath(llvm::ArrayRef<wchar_t> nt_path) {
     return result;
   } while (::FindNextVolumeW(vol_iter, vol_name.data(), vol_name.size()));
 
-  std::wstring nt_str(nt_path.data(),
-                      ::wcsnlen(nt_path.data(), nt_path.size()));
-  std::string nt_utf8;
-  llvm::convertWideToUTF8(nt_str, nt_utf8);
-  LLDB_LOG(log,
-           "ConvertNtDevicePathToDosPath: no matching volume found for "
-           "nt_path \"{0}\"",
-           nt_utf8);
+  LLDB_LOG(log, "ConvertNtDevicePathToDosPath: no matching volume found");
   return std::nullopt;
 }
 
@@ -593,15 +586,10 @@ static std::optional<std::string> GetFileNameFromHandleFallback(HANDLE hFile) {
 
 static std::optional<std::string> GetFileNameByLoadAddress(HANDLE hProcess,
                                                            LPVOID base_addr) {
-  Log *log = GetLog(WindowsLog::Event);
   std::array<wchar_t, MAX_PATH + 1> module_filename;
   DWORD len =
       ::GetModuleFileNameExW(hProcess, reinterpret_cast<HMODULE>(base_addr),
                              module_filename.data(), module_filename.size());
-  LLDB_LOG(log,
-           "GetFileNameByLoadAddress: GetModuleFileNameExW(base={0:x}) "
-           "len={1}, error={2}",
-           base_addr, len, ::GetLastError());
   if (len > 0 && len < module_filename.size()) {
     std::string path_utf8;
     llvm::convertWideToUTF8(std::wstring(module_filename.data(), len),
@@ -617,141 +605,52 @@ static std::optional<std::string> GetFileNameByLoadAddress(HANDLE hProcess,
         hProcess, base_addr, mapped_filename.data(), mapped_filename.size());
     if (mapped_len < mapped_filename.size())
       break;
-    if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
-      LLDB_LOG(log,
-               "GetFileNameByLoadAddress: GetMappedFileNameW(base={0:x}) "
-               "failed, buffer={1}, error={2}",
-               base_addr, mapped_filename.size(), ::GetLastError());
+    if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
       return std::nullopt;
-    }
     mapped_filename.resize(mapped_filename.size() * 2);
   }
-  LLDB_LOG(log,
-           "GetFileNameByLoadAddress: GetMappedFileNameW(base={0:x}) len={1}",
-           base_addr, mapped_len);
   std::optional<std::string> dos_path = ConvertNtDevicePathToDosPath(
       llvm::ArrayRef<wchar_t>(mapped_filename.data(), mapped_len + 1));
-  LLDB_LOG(log,
-           "GetFileNameByLoadAddress: ConvertNtDevicePathToDosPath -> {0}",
-           dos_path ? *dos_path : "<nullopt>");
   return dos_path;
 }
 
-// Determine how many bytes can be read at `addr` in `hProcess` before crossing
-// out of the committed memory region containing it. Returns 0 if the address
-// is not within a committed region.
-static SIZE_T BytesReadableAt(HANDLE hProcess, LPCVOID addr) {
-  MEMORY_BASIC_INFORMATION mbi{};
-  if (!::VirtualQueryEx(hProcess, addr, &mbi, sizeof(mbi)))
-    return 0;
-  if (mbi.State != MEM_COMMIT)
-    return 0;
-  uintptr_t region_end =
-      reinterpret_cast<uintptr_t>(mbi.BaseAddress) + mbi.RegionSize;
-  uintptr_t a = reinterpret_cast<uintptr_t>(addr);
-  if (a >= region_end)
-    return 0;
-  return region_end - a;
-}
-
 // Resolve the LOAD_DLL_DEBUG_INFO::lpImageName field.
 static std::optional<std::string>
 GetFileNameFromImageNameField(HANDLE hProcess,
                               const LOAD_DLL_DEBUG_INFO &info) {
-  Log *log = GetLog(WindowsLog::Event);
-  if (info.lpImageName == nullptr) {
-    LLDB_LOG(log, "GetFileNameFromImageNameField: lpImageName is null");
+  if (info.lpImageName == nullptr)
     return std::nullopt;
-  }
 
   LPVOID name_addr = nullptr;
   SIZE_T bytes_read = 0;
   if (!::ReadProcessMemory(hProcess, info.lpImageName, &name_addr,
                            sizeof(name_addr), &bytes_read) ||
-      bytes_read != sizeof(name_addr) || name_addr == nullptr) {
-    LLDB_LOG(log,
-             "GetFileNameFromImageNameField: ReadProcessMemory(lpImageName="
-             "{0:x}) bytes_read={1}, name_addr={2:x}, error={3}",
-             info.lpImageName, bytes_read, name_addr, ::GetLastError());
+      bytes_read != sizeof(name_addr) || name_addr == nullptr)
     return std::nullopt;
-  }
 
   if (info.fUnicode) {
     std::array<wchar_t, MAX_PATH + 1> wbuf{};
-    // Bound the read by the size of the committed region at name_addr to
-    // avoid ERROR_PARTIAL_COPY when the path is short and the buffer would
-    // otherwise span into an unmapped page.
-    SIZE_T to_read =
-        std::min<SIZE_T>(wbuf.size() * sizeof(wchar_t),
-                         BytesReadableAt(hProcess, name_addr));
-    to_read &= ~SIZE_T(1); // round down to a wchar_t boundary
-    if (to_read < sizeof(wchar_t)) {
-      LLDB_LOG(log,
-               "GetFileNameFromImageNameField: no readable bytes at "
-               "name_addr={0:x}",
-               name_addr);
-      return std::nullopt;
-    }
-    if (!::ReadProcessMemory(hProcess, name_addr, wbuf.data(), to_read,
-                             &bytes_read)) {
-      LLDB_LOG(log,
-               "GetFileNameFromImageNameField: ReadProcessMemory(unicode "
-               "name_addr={0:x}, to_read={1}) failed, error={2}",
-               name_addr, to_read, ::GetLastError());
-      return std::nullopt;
-    }
-    size_t max_chars = bytes_read / sizeof(wchar_t);
-    size_t wlen = ::wcsnlen(wbuf.data(), max_chars);
-    if (wlen == 0) {
-      LLDB_LOG(log, "GetFileNameFromImageNameField: unicode name is empty");
+    if (!::ReadProcessMemory(hProcess, name_addr, wbuf.data(),
+                             wbuf.size() * sizeof(wchar_t), &bytes_read))
       return std::nullopt;
-    }
-    if (wlen == max_chars) {
-      LLDB_LOG(log,
-               "GetFileNameFromImageNameField: unicode name not "
-               "null-terminated within {0} chars",
-               max_chars);
+    if (wbuf[MAX_PATH] != L'\0')
       return std::nullopt;
-    }
     std::string path_utf8;
-    llvm::convertWideToUTF8(std::wstring(wbuf.data(), wlen), path_utf8);
-    LLDB_LOG(log, "GetFileNameFromImageNameField: unicode resolved -> {0}",
-             path_utf8);
+    llvm::convertWideToUTF8(wbuf.data(), path_utf8);
+    if (path_utf8.empty())
+      return std::nullopt;
     return path_utf8;
   }
 
   std::array<char, MAX_PATH + 1> abuf{};
-  SIZE_T to_read =
-      std::min<SIZE_T>(abuf.size(), BytesReadableAt(hProcess, name_addr));
-  if (to_read == 0) {
-    LLDB_LOG(log,
-             "GetFileNameFromImageNameField: no readable bytes at "
-             "name_addr={0:x}",
-             name_addr);
+  if (!::ReadProcessMemory(hProcess, name_addr, abuf.data(), abuf.size(),
+                           &bytes_read))
     return std::nullopt;
-  }
-  if (!::ReadProcessMemory(hProcess, name_addr, abuf.data(), to_read,
-                           &bytes_read)) {
-    LLDB_LOG(log,
-             "GetFileNameFromImageNameField: ReadProcessMemory(ascii "
-             "name_addr={0:x}, to_read={1}) failed, error={2}",
-             name_addr, to_read, ::GetLastError());
+  if (abuf[MAX_PATH] != '\0')
     return std::nullopt;
-  }
-  size_t alen = ::strnlen(abuf.data(), bytes_read);
-  if (alen == 0) {
-    LLDB_LOG(log, "GetFileNameFromImageNameField: ascii name is empty");
+  std::string path(abuf.data());
+  if (path.empty())
     return std::nullopt;
-  }
-  if (alen == bytes_read) {
-    LLDB_LOG(log,
-             "GetFileNameFromImageNameField: ascii name not null-terminated "
-             "within {0} bytes",
-             bytes_read);
-    return std::nullopt;
-  }
-  std::string path(abuf.data(), alen);
-  LLDB_LOG(log, "GetFileNameFromImageNameField: ascii resolved -> {0}", path);
   return path;
 }
 
@@ -759,10 +658,6 @@ DWORD
 DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info,
                                    DWORD thread_id) {
   Log *log = GetLog(WindowsLog::Event);
-  LLDB_LOG(log,
-           "HandleLoadDllEvent: hFile={0}, lpBaseOfDll={1:x}, "
-           "lpImageName={2:x}, fUnicode={3}",
-           info.hFile, info.lpBaseOfDll, info.lpImageName, info.fUnicode);
 
   auto on_load_dll = [&](llvm::StringRef path) {
     FileSpec file_spec(path);
@@ -789,17 +684,8 @@ DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info,
       llvm::StringRef path_str = path_str_utf8;
       path_str.consume_front("\\\\?\\");
       resolved_path = path_str.str();
-      LLDB_LOG(log,
-               "HandleLoadDllEvent: GetFinalPathNameByHandleW resolved -> {0}",
-               *resolved_path);
     } else {
-      LLDB_LOG(log,
-               "HandleLoadDllEvent: GetFinalPathNameByHandleW failed, error={0}"
-               ", trying GetFileNameFromHandleFallback",
-               ::GetLastError());
       resolved_path = GetFileNameFromHandleFallback(info.hFile);
-      LLDB_LOG(log, "HandleLoadDllEvent: GetFileNameFromHandleFallback -> {0}",
-               resolved_path ? *resolved_path : "<nullopt>");
     }
   }
 



More information about the lldb-commits mailing list