Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lldb/packages/Python/lldbsuite/test/builders/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,8 @@ def _getDebugInfoArgs(self, debug_info):
"gmodules": {"MAKE_DSYM": "NO", "MAKE_GMODULES": "YES"},
"debug_names": {"MAKE_DEBUG_NAMES": "YES"},
"dwp": {"MAKE_DSYM": "NO", "MAKE_DWP": "YES"},
"native-pdb": {"DEBUG_INFO_FLAG": "-g"},
"dia-pdb": {"DEBUG_INFO_FLAG": "-g"},
}

# Collect all flags, with later options overriding earlier ones
Expand Down
42 changes: 34 additions & 8 deletions lldb/packages/Python/lldbsuite/test/lldbtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,13 @@ def setUpCommands(cls):
)
return commands

def getDebugInfoSetupCommands(self):
if self.getDebugInfo() == "native-pdb":
Copy link
Member

@Michael137 Michael137 Aug 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not fold this into setUpCommands? Then we don't need to loop over these separately

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setUpCommands is a @classmethod, so it gets the calling class type as it's argument, not the instance. I don't know if/why @classmethod is needed there.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know that for sure, but I can imagine it being added just because the function didn't need the instance argument at the time. It may be possible to remove it.

That said, I'm not entirely happy with how these new categories are are behaving quite differently from the other debug info categories. The other categories change the kind of debug info that's being emitted -- not which code is parsing that debug info.

Having a pdb category to get clang to produce pdb debug info makes perfect sense. I'm not so sure about using that category to select the plugin kind -- particularly if the end goal is to remove the non-native plugin completely.

When I made the suggestion to use settings I was imagining you would be setting it on a per-run basis via the --setting flag to dotest.py. Would that be an option?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I made the suggestion to use settings I was imagining you would be setting it on a per-run basis via the --setting flag to dotest.py. Would that be an option?

That's possible, but then we wouldn't be able to run the tests with both plugins in CI using check-lldb, right?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's correct. Is that your goal? (I haven't been following the overall discussion too closely).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could implement this, ideally with a reduced scope check-lldb-pdbstuff.

Or we could use dotest.py directly? Anything that cuts down the time because the test step is already around 25 minutes.

It's ugly but could you come up with dotest.py -p ?

Actually, whatever way this is done, a check-lldb-supersecretpdbthing is better because then I only have to add that to llvm-zorg once. Any future changes to what gets run can be done in llvm-project and take effect right away.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this world, the command to run all pdb tests with the non-default plugin would be something like llvm-lit --dotest-args="--category pdb --setting plugin.symbol-file.pdb.reader=foo". Besides needing to update zorg, another disadvantage of this approach is that there isn't a particularly clean way to skip/xfail a test for a particular pdb plugin, as the --setting thingy sort of works behind the back of the decorators.

I've been thinking about this, and I think I've come to a conclusion that the thing that upsets me is not so much the existence of the category, as it's the existence of the plugin that it is testing. Ignoring the implementation differences, the difference in test coverage between native-pdb and dia-pdb is much bigger than "dwarf" and "dwo". It's kind of like "dwarf" and "dsym", but even bigger because the debug map eventually goes back to the dwarf implementation to parse the debug info. So, if those categories make sense (personally, I'm not convinced they all do), then these sort of do as well.

However, the very concept of trying to support both plugins bothers me. Windows is already the least supported lldb platform (counted by the number of passing tests for instance) and the one with the smallest number of active developers supporting it. Having those developers split their time trying to support both plugins sounds like a very bad idea to me. In fact, I would speculate that the reason that we still have two plugins is because there isn't a developer with sufficient time to actually merge the two.

So, if we're going to put our foot down for something, I think this should be the reason -- basically, say "we don't support more pdb things until pdb gets its act together". Unfortunately, I'm not in a position to be putting my foot down right now. However, if someone else (wink, wink) wants to put his foot down, I will support that foot however I can.

Copy link
Member

@Michael137 Michael137 Aug 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How unusable is the Native PDB plugin to debug with? Can we just make it the default now? I know there's some tests that pass with DIA PDB that don't with the native one, but are those actually blockers?

@Nerixyz @charles-zablit any big gaps that you're aware of?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll start a discourse thread for this. Linaro has reason to invest in Windows.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://discourse.llvm.org/t/rfc-removing-the-dia-pdb-plugin-from-lldb/87827

Once there's clarity there we can make a clear decision here too.

return ["settings set plugin.symbol-file.pdb.reader native"]
if self.getDebugInfo() == "dia-pdb":
return ["settings set plugin.symbol-file.pdb.reader dia"]
return []

def setUp(self):
"""Fixture for unittest test case setup.

Expand All @@ -828,13 +835,6 @@ def setUp(self):
else:
self.lldbDAPExec = None

self.lldbOption = " ".join("-o '" + s + "'" for s in self.setUpCommands())

# If we spawn an lldb process for test (via pexpect), do not load the
# init file unless told otherwise.
if os.environ.get("NO_LLDBINIT") != "NO":
self.lldbOption += " --no-lldbinit"

# Assign the test method name to self.testMethodName.
#
# For an example of the use of this attribute, look at test/types dir.
Expand All @@ -843,6 +843,14 @@ def setUp(self):
# used for all the test cases.
self.testMethodName = self._testMethodName

setUpCommands = self.setUpCommands() + self.getDebugInfoSetupCommands()
self.lldbOption = " ".join("-o '" + s + "'" for s in setUpCommands)

# If we spawn an lldb process for test (via pexpect), do not load the
# init file unless told otherwise.
if os.environ.get("NO_LLDBINIT") != "NO":
self.lldbOption += " --no-lldbinit"

# This is for the case of directly spawning 'lldb'/'gdb' and interacting
# with it using pexpect.
self.child = None
Expand Down Expand Up @@ -1792,6 +1800,12 @@ def no_reason(_):
if can_replicate
]

# PDB is off by default, because it has a lot of failures right now.
# See llvm.org/pr149498
if original_testcase.TEST_WITH_PDB_DEBUG_INFO:
dbginfo_categories.append("native-pdb")
dbginfo_categories.append("dia-pdb")

xfail_for_debug_info_cat_fn = getattr(
attrvalue, "__xfail_for_debug_info_cat_fn__", no_reason
)
Expand Down Expand Up @@ -1879,6 +1893,14 @@ class TestBase(Base, metaclass=LLDBTestCaseFactory):
# test multiple times with various debug info types.
NO_DEBUG_INFO_TESTCASE = False

TEST_WITH_PDB_DEBUG_INFO = False
"""
Subclasses can set this to True to test with both native and DIA PDB in addition to
the other debug info types. This id off by default because many tests will
fail due to missing functionality in PDB.
See llvm.org/pr149498.
"""

def generateSource(self, source):
template = source + ".template"
temp = os.path.join(self.getSourceDir(), template)
Expand Down Expand Up @@ -1918,6 +1940,8 @@ def setUp(self):

for s in self.setUpCommands():
self.runCmd(s)
for s in self.getDebugInfoSetupCommands():
self.runCmd(s)

# We want our debugger to be synchronous.
self.dbg.SetAsync(False)
Expand Down Expand Up @@ -2264,7 +2288,9 @@ def completions_match(self, command, completions, max_completions=-1):
given list of completions"""
interp = self.dbg.GetCommandInterpreter()
match_strings = lldb.SBStringList()
interp.HandleCompletion(command, len(command), 0, max_completions, match_strings)
interp.HandleCompletion(
command, len(command), 0, max_completions, match_strings
)
# match_strings is a 1-indexed list, so we have to slice...
self.assertCountEqual(
completions, list(match_strings)[1:], "List of returned completion is wrong"
Expand Down
16 changes: 15 additions & 1 deletion lldb/packages/Python/lldbsuite/test/test_categories.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

# System modules
import sys
import os

# Third-party modules

Expand All @@ -12,13 +13,21 @@

# Key: Category name
# Value: should be used in lldbtest's debug-info replication
debug_info_categories = {"dwarf": True, "dwo": True, "dsym": True, "gmodules": False}
debug_info_categories = {
"dwarf": True,
"dwo": True,
"dsym": True,
"native-pdb": False,
"dia-pdb": False,
"gmodules": False,
}

all_categories = {
"basic_process": "Basic process execution sniff tests.",
"cmdline": "Tests related to the LLDB command-line interface",
"dataformatters": "Tests related to the type command and the data formatters subsystem",
"debugserver": "Debugserver tests",
"dia-pdb": "Tests that can be run with PDB debug information using the DIA PDB plugin",
"dsym": "Tests that can be run with DSYM debug information",
"dwarf": "Tests that can be run with DWARF debug information",
"dwo": "Tests that can be run with DWO debug information",
Expand All @@ -34,6 +43,7 @@
"lldb-dap": "Tests for the Debug Adapter Protocol with lldb-dap",
"llgs": "Tests for the gdb-server functionality of lldb-server",
"msvcstl": "Test for MSVC STL data formatters",
"native-pdb": "Tests that can be run with PDB debug information using the native PDB plugin",
"pexpect": "Tests requiring the pexpect library to be available",
"objc": "Tests related to the Objective-C programming language support",
"pyapi": "Tests related to the Python API",
Expand Down Expand Up @@ -65,6 +75,10 @@ def is_supported_on_platform(category, platform, compiler_path):
if platform not in ["darwin", "macosx", "ios", "watchos", "tvos", "bridgeos"]:
return False
return gmodules.is_compiler_clang_with_gmodules(compiler_path)
elif category == "native-pdb":
return platform == "windows"
elif category == "dia-pdb":
return os.environ.get("LLVM_ENABLE_DIA_SDK", None) == "1"
return True


Expand Down
2 changes: 2 additions & 0 deletions lldb/test/API/lit.cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,8 @@ def delete_module_cache(path):
for v in ["SystemDrive"]:
if v in os.environ:
config.environment[v] = os.environ[v]
if config.llvm_enable_dia_sdk:
config.environment["LLVM_ENABLE_DIA_SDK"] = "1"

# Some steps required to initialize the tests dynamically link with python.dll
# and need to know the location of the Python libraries. This ensures that we
Expand Down
3 changes: 3 additions & 0 deletions lldb/test/API/lit.site.cfg.py.in
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
@LIT_SITE_CFG_IN_HEADER@

import lit.util

config.llvm_src_root = "@LLVM_SOURCE_DIR@"
config.llvm_obj_root = "@LLVM_BINARY_DIR@"
config.llvm_tools_dir = lit_config.substitute("@LLVM_TOOLS_DIR@")
config.llvm_libs_dir = lit_config.substitute("@LLVM_LIBS_DIR@")
config.llvm_include_dir = lit_config.substitute("@LLVM_INCLUDE_DIR@")
config.llvm_shlib_dir = lit_config.substitute("@SHLIBDIR@")
config.llvm_build_mode = lit_config.substitute("@LLVM_BUILD_MODE@")
config.llvm_enable_dia_sdk = lit.util.pythonize_bool("@LLVM_ENABLE_DIA_SDK@")
config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@"
config.lldb_obj_root = lit_config.substitute("@LLDB_BINARY_DIR@")
config.lldb_src_root = "@LLDB_SOURCE_DIR@"
Expand Down
3 changes: 3 additions & 0 deletions lldb/test/API/test_utils/pdb/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
CXX_SOURCES := main.cpp

include Makefile.rules
20 changes: 20 additions & 0 deletions lldb/test/API/test_utils/pdb/TestPdb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"""
Test PDB enabled tests
"""

from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *


class TestBuildMethod(TestBase):
TEST_WITH_PDB_DEBUG_INFO = True

def test(self):
self.build()
self.assertTrue(self.dbg.CreateTarget(self.getBuildArtifact()))
if self.getDebugInfo() == "native-pdb":
self.expect(
"target modules dump symfile", substrs=["SymbolFile native-pdb"]
)
if self.getDebugInfo() == "dia-pdb":
self.expect("target modules dump symfile", substrs=["SymbolFile pdb"])
1 change: 1 addition & 0 deletions lldb/test/API/test_utils/pdb/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
int main() { return 0; }
Loading