[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
Thu May 28 07:16:25 PDT 2026
https://github.com/charles-zablit updated https://github.com/llvm/llvm-project/pull/198630
>From 29b3b3676be9d2b7fdc2ee47d365687a74c82de8 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/5] 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 8026c98328a2c..f03dc4b835112 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 8fdbe8c08ebc552776a0a268233a48153c4fd18b Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Thu, 28 May 2026 14:11:37 +0100
Subject: [PATCH 2/5] [lldb][windows] log each LOAD_DLL resolution step +
collect logs in CI
Add granular LLDB_LOG calls in HandleLoadDllEvent and its helpers so we
can see, per LOAD_DLL_DEBUG_EVENT, exactly which path resolution
fallback was tried and why each one returned nullopt. This is meant to
diagnose the Windows Server Core container case where kernel32.dll,
KernelBase.dll and ucrtbase.dll never get added to the module list.
To make these logs visible at the end of a GitHub Actions run:
- .ci/monolithic-windows.sh now passes
LLDB_TEST_USER_ARGS="--channel;lldb event" so dotest enables the
"lldb event" channel for every test (writes <test>-host.log).
- .ci/utils.sh's at-exit copies Failure_*.log, *-host.log,
ExpectedFailure_*.log and UnexpectedSuccess_*.log from
build/lldb-test-build.noindex into artifacts/lldb-test-logs/,
preserving directory structure. The artifacts/ directory is
already uploaded by the Premerge Artifacts (Windows) step.
---
.ci/monolithic-windows.sh | 1 +
.ci/utils.sh | 17 ++++
.../Process/Windows/Common/DebuggerThread.cpp | 80 ++++++++++++++++---
3 files changed, 87 insertions(+), 11 deletions(-)
diff --git a/.ci/monolithic-windows.sh b/.ci/monolithic-windows.sh
index 67cbebb1beb5c..6d08f8f1706e8 100755
--- a/.ci/monolithic-windows.sh
+++ b/.ci/monolithic-windows.sh
@@ -57,6 +57,7 @@ cmake -S "${MONOREPO_ROOT}"/llvm -B "${BUILD_DIR}" \
-D CMAKE_MODULE_LINKER_FLAGS="/MANIFEST:NO" \
-D CMAKE_SHARED_LINKER_FLAGS="/MANIFEST:NO" \
-D LLVM_ENABLE_RUNTIMES="${runtimes}" \
+ -D LLDB_TEST_USER_ARGS="--channel;lldb event" \
"${runtime_cmake_args[@]}"
start-group "ninja"
diff --git a/.ci/utils.sh b/.ci/utils.sh
index f14fe753415ce..b0eb25260f073 100644
--- a/.ci/utils.sh
+++ b/.ci/utils.sh
@@ -30,6 +30,23 @@ 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.
+ lldb_test_log_root="${BUILD_DIR}/lldb-test-build.noindex"
+ if [[ -d "${lldb_test_log_root}" ]]; then
+ mkdir -p artifacts/lldb-test-logs
+ # Failure_*.log: dotest session output captured on test failure.
+ # *-host.log: LLDB_LOG output from channels enabled via --channel.
+ while IFS= read -r -d '' f; do
+ rel="${f#${lldb_test_log_root}/}"
+ mkdir -p "artifacts/lldb-test-logs/$(dirname "${rel}")"
+ cp "${f}" "artifacts/lldb-test-logs/${rel}" || :
+ done < <(find "${lldb_test_log_root}" \
+ \( -name 'Failure_*.log' -o -name '*-host.log' \
+ -o -name 'ExpectedFailure_*.log' -o -name 'UnexpectedSuccess_*.log' \) \
+ -print0)
+ fi
+
# If building fails there will be no results files.
shopt -s nullglob
diff --git a/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp b/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp
index c4bfa11e9635d..af7496a631e67 100644
--- a/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp
@@ -543,10 +543,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),
@@ -556,49 +561,89 @@ static std::optional<std::string> GetFileNameByLoadAddress(HANDLE hProcess,
// Fallback: ask the kernel for the file backing the mapping at this address.
std::array<wchar_t, MAX_PATH + 1> mapped_filename;
- if (!::GetMappedFileNameW(hProcess, base_addr, mapped_filename.data(),
- mapped_filename.size()))
+ DWORD mapped_len = ::GetMappedFileNameW(
+ hProcess, base_addr, mapped_filename.data(), mapped_filename.size());
+ LLDB_LOG(log,
+ "GetFileNameByLoadAddress: GetMappedFileNameW(base={0:x}) "
+ "len={1}, error={2}",
+ base_addr, mapped_len, ::GetLastError());
+ if (!mapped_len)
return std::nullopt;
- return ConvertNtDevicePathToDosPath(mapped_filename);
+ std::optional<std::string> dos_path =
+ ConvertNtDevicePathToDosPath(mapped_filename);
+ LLDB_LOG(log,
+ "GetFileNameByLoadAddress: ConvertNtDevicePathToDosPath -> {0}",
+ dos_path ? *dos_path : "<nullopt>");
+ return dos_path;
}
// 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))
+ wbuf.size() * sizeof(wchar_t), &bytes_read)) {
+ LLDB_LOG(log,
+ "GetFileNameFromImageNameField: ReadProcessMemory(unicode "
+ "name_addr={0:x}) failed, error={1}",
+ name_addr, ::GetLastError());
return std::nullopt;
- if (wbuf[MAX_PATH] != L'\0')
+ }
+ if (wbuf[MAX_PATH] != L'\0') {
+ LLDB_LOG(log,
+ "GetFileNameFromImageNameField: unicode name not "
+ "null-terminated within MAX_PATH");
return std::nullopt;
+ }
std::string path_utf8;
llvm::convertWideToUTF8(wbuf.data(), path_utf8);
- if (path_utf8.empty())
+ if (path_utf8.empty()) {
+ LLDB_LOG(log, "GetFileNameFromImageNameField: unicode name is empty");
return std::nullopt;
+ }
return path_utf8;
}
std::array<char, MAX_PATH + 1> abuf{};
if (!::ReadProcessMemory(hProcess, name_addr, abuf.data(), abuf.size(),
- &bytes_read))
+ &bytes_read)) {
+ LLDB_LOG(log,
+ "GetFileNameFromImageNameField: ReadProcessMemory(ascii "
+ "name_addr={0:x}) failed, error={1}",
+ name_addr, ::GetLastError());
return std::nullopt;
- if (abuf[MAX_PATH] != '\0')
+ }
+ if (abuf[MAX_PATH] != '\0') {
+ LLDB_LOG(log,
+ "GetFileNameFromImageNameField: ascii name not null-terminated "
+ "within MAX_PATH");
return std::nullopt;
+ }
std::string path(abuf.data());
- if (path.empty())
+ if (path.empty()) {
+ LLDB_LOG(log, "GetFileNameFromImageNameField: ascii name is empty");
return std::nullopt;
+ }
return path;
}
@@ -606,6 +651,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);
@@ -632,8 +681,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 96cbc9709ec99693baf8ec918e8ae6705c3703b1 Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Thu, 28 May 2026 14:16:04 +0100
Subject: [PATCH 3/5] [ci][windows] drop lld from project list to speed up
check-lldb turnaround
check-lldb on Windows links its test inputs with the MSVC toolchain, so
lld is not in the transitive dependency graph of the check-lldb target.
Dropping it from LLVM_ENABLE_PROJECTS skips its CMake configure step
without affecting test coverage. Test execution was already restricted
to check-lldb only by the existing DIAGNOSTIC block.
---
.github/workflows/premerge.yaml | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/premerge.yaml b/.github/workflows/premerge.yaml
index f03dc4b835112..0001e40bec36d 100644
--- a/.github/workflows/premerge.yaml
+++ b/.github/workflows/premerge.yaml
@@ -159,8 +159,10 @@ 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.
- echo "windows-projects=clang;lld;lldb;llvm" >> $GITHUB_OUTPUT
+ # waiting on the rest of llvm/clang/lld/etc. lld is dropped from
+ # the project list since check-lldb does not depend on it on
+ # Windows (tests link with the MSVC toolchain).
+ echo "windows-projects=clang;lldb;llvm" >> $GITHUB_OUTPUT
echo "windows-check-targets=check-lldb" >> $GITHUB_OUTPUT
echo "windows-runtimes=" >> $GITHUB_OUTPUT
echo "windows-runtimes-check-targets=" >> $GITHUB_OUTPUT
>From 5faa5fb7c089e80d1d168bbb4c78297fffc936cb Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Thu, 28 May 2026 14:43:54 +0100
Subject: [PATCH 4/5] Revert "[ci][windows] drop lld from project list"
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The lldb API test driver links test inferiors with `-fuse-ld=lld`
(see lldb/packages/Python/lldbsuite/test/make/Makefile.rules), so
removing lld breaks every API test that builds an inferior — 597 of
them on the last run. Restore lld in LLVM_ENABLE_PROJECTS.
---
.github/workflows/premerge.yaml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/premerge.yaml b/.github/workflows/premerge.yaml
index 0001e40bec36d..173efe1ff4c98 100644
--- a/.github/workflows/premerge.yaml
+++ b/.github/workflows/premerge.yaml
@@ -159,10 +159,10 @@ 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. lld is dropped from
- # the project list since check-lldb does not depend on it on
- # Windows (tests link with the MSVC toolchain).
- echo "windows-projects=clang;lldb;llvm" >> $GITHUB_OUTPUT
+ # 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
echo "windows-runtimes-check-targets=" >> $GITHUB_OUTPUT
>From ea2a72019bd47d2eccb45f382fa7d018886c0c9f Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Thu, 28 May 2026 15:14:13 +0100
Subject: [PATCH 5/5] [ci] harden lldb test log collection in at-exit
The previous version sometimes failed to produce artifacts/lldb-test-logs/
in CI runs even though the `Failure_*.log` and `*-host.log` files clearly
existed under build/lldb-test-build.noindex/. The most likely culprit is
`set -e` aborting the trap when an inner mkdir/cp returned non-zero
(e.g. on a long Windows path). Wrap the block in `set +e` so any
collection failure is contained and cannot skip the GitHub Actions
reporting block. Also print a summary line so we can see in the CI log
how many files were copied (or that the directory was missing).
---
.ci/utils.sh | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/.ci/utils.sh b/.ci/utils.sh
index b0eb25260f073..3d575614e9218 100644
--- a/.ci/utils.sh
+++ b/.ci/utils.sh
@@ -32,20 +32,30 @@ function at-exit {
# 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
lldb_test_log_root="${BUILD_DIR}/lldb-test-build.noindex"
+ echo "at-exit: collecting lldb test logs from ${lldb_test_log_root}"
if [[ -d "${lldb_test_log_root}" ]]; then
mkdir -p artifacts/lldb-test-logs
# Failure_*.log: dotest session output captured on test failure.
# *-host.log: LLDB_LOG output from channels enabled via --channel.
+ matched=0
while IFS= read -r -d '' f; do
rel="${f#${lldb_test_log_root}/}"
- mkdir -p "artifacts/lldb-test-logs/$(dirname "${rel}")"
- cp "${f}" "artifacts/lldb-test-logs/${rel}" || :
+ 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 < <(find "${lldb_test_log_root}" \
\( -name 'Failure_*.log' -o -name '*-host.log' \
-o -name 'ExpectedFailure_*.log' -o -name 'UnexpectedSuccess_*.log' \) \
- -print0)
+ -print0 2>/dev/null)
+ echo "at-exit: copied ${matched} lldb test log files"
+ else
+ echo "at-exit: lldb test log root does not exist, skipping"
fi
+ set -e
# If building fails there will be no results files.
shopt -s nullglob
More information about the lldb-commits
mailing list