Skip to content

[lldb][lldb-dap] Cleanup breakpoint filters. #87550

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 29, 2024
Merged

Conversation

oontvoo
Copy link
Member

@oontvoo oontvoo commented Apr 3, 2024

Details:

  • remove Swift breakpoint filter because this version of LLDB does not support Swift.
  • only return objc filters when working on macos.

@oontvoo oontvoo requested a review from JDevlieghere as a code owner April 3, 2024 20:16
@llvmbot llvmbot added the lldb label Apr 3, 2024
@llvmbot
Copy link
Member

llvmbot commented Apr 3, 2024

@llvm/pr-subscribers-lldb

Author: Vy Nguyen (oontvoo)

Changes

Details:

  • remove Swift breakpoint filter because this version of LLDB does not support Swift.
  • only return objc filters when working on macos.

Full diff: https://github.com/llvm/llvm-project/pull/87550.diff

2 Files Affected:

  • (modified) lldb/tools/lldb-dap/DAP.cpp (+1-3)
  • (modified) lldb/tools/lldb-dap/lldb-dap.cpp (+7)
diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp
index b254ddfef0d5ff..52e607350407ab 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -36,9 +36,7 @@ DAP::DAP()
           {{"cpp_catch", "C++ Catch", lldb::eLanguageTypeC_plus_plus},
            {"cpp_throw", "C++ Throw", lldb::eLanguageTypeC_plus_plus},
            {"objc_catch", "Objective-C Catch", lldb::eLanguageTypeObjC},
-           {"objc_throw", "Objective-C Throw", lldb::eLanguageTypeObjC},
-           {"swift_catch", "Swift Catch", lldb::eLanguageTypeSwift},
-           {"swift_throw", "Swift Throw", lldb::eLanguageTypeSwift}}),
+           {"objc_throw", "Objective-C Throw", lldb::eLanguageTypeObjC}}),
       focus_tid(LLDB_INVALID_THREAD_ID), sent_terminated_event(false),
       stop_at_entry(false), is_attach(false),
       enable_auto_variable_summaries(false),
diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp
index 55f8c920e60016..5f5014eaab90f0 100644
--- a/lldb/tools/lldb-dap/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/lldb-dap.cpp
@@ -1628,7 +1628,14 @@ void request_initialize(const llvm::json::Object &request) {
   body.try_emplace("supportsEvaluateForHovers", true);
   // Available filters or options for the setExceptionBreakpoints request.
   llvm::json::Array filters;
+  std::string triple =
+      std::string(g_dap.debugger.GetSelectedPlatform().GetTriple());
   for (const auto &exc_bp : g_dap.exception_breakpoints) {
+    // Skipping objc breakpoint filters if not working on macos.
+    if (exc_bp.language == lldb::eLanguageTypeObjC &&
+        triple.find("macos") == std::string::npos) {
+      continue;
+    }
     filters.emplace_back(CreateExceptionBreakpointFilter(exc_bp));
   }
   body.try_emplace("exceptionBreakpointFilters", std::move(filters));

@oontvoo oontvoo requested review from labath and cmtice and removed request for cmtice April 3, 2024 20:17
for (const auto &exc_bp : g_dap.exception_breakpoints) {
// Skipping objc breakpoint filters if not working on macos.
Copy link
Collaborator

Choose a reason for hiding this comment

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

GNUStep is still a thing. It's likely the exception throw breakpoint is the only part of our ObjC support that would work with GNUStep, however, so maybe this doesn't matter all that much.

Copy link
Collaborator

@clayborg clayborg left a comment

Choose a reason for hiding this comment

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

I would be nice if we can detect if we support Swift dynamically. Internally in LLDB, we can ask for a TypeSystem by language using:

llvm::Expected<lldb::TypeSystemSP>
TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language,
                                        Module *module, bool can_create);
llvm::Expected<lldb::TypeSystemSP>
TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language,
                                        Target *target, bool can_create);

These functions will return respectively:

TypeSystem::CreateInstance(language, module);
TypeSystem::CreateInstance(language, target);

We should be able to add a new static method to the TypeSystem.h/.cpp that can answer if a language is supported with something like:

static bool TypeSystem::SupportsLanguage(lldb::LanguageType language);

Each TypeSystem plugin can register a new callback that can answer if they support a language. Then we can add a static function on SBDebugger that would expose this function with something like:

static bool SBDebugger::SupportsLanguage(lldb::LanguageType language);

I will make comments in the DAP.cpp where this would be used.

Comment on lines 36 to 39
{{"cpp_catch", "C++ Catch", lldb::eLanguageTypeC_plus_plus},
{"cpp_throw", "C++ Throw", lldb::eLanguageTypeC_plus_plus},
{"objc_catch", "Objective-C Catch", lldb::eLanguageTypeObjC},
{"objc_throw", "Objective-C Throw", lldb::eLanguageTypeObjC},
{"swift_catch", "Swift Catch", lldb::eLanguageTypeSwift},
{"swift_throw", "Swift Throw", lldb::eLanguageTypeSwift}}),
{"objc_throw", "Objective-C Throw", lldb::eLanguageTypeObjC}}),
Copy link
Collaborator

Choose a reason for hiding this comment

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

See my comments for this patch in the review. It would be great to determine if a language is supported by LLDB dynamically and only add support for languages that the current LLDB supports. So we would probably need to default construct the exception_breakpoints() and then inside this constructor or before we try to use exception_breakpoints, we would need to populate it by doing something like:

if (g_dap.debugger.SupportsLanguage(lldb::eLanguageTypeC_plus_plus)) {
  exception_breakpoints.emplace_back({"cpp_catch", "C++ Catch", lldb::eLanguageTypeC_plus_plus})
  exception_breakpoints.emplace_back("cpp_throw", "C++ Throw", lldb::eLanguageTypeC_plus_plus})
}
if (g_dap.debugger.SupportsLanguage(lldb::eLanguageTypeObjC)) {
  exception_breakpoints.emplace_back({"objc_catch", "Objective-C Catch", lldb::eLanguageTypeObjC})
  exception_breakpoints.emplace_back("objc_throw", "Objective-C Throw", lldb::eLanguageTypeObjC})
}
if (g_dap.debugger.SupportsLanguage(lldb:: eLanguageTypeSwift)) {
  exception_breakpoints.emplace_back({"swift_catch", "Swift Catch", lldb:: eLanguageTypeSwift})
  exception_breakpoints.emplace_back("swift_throw", "Swift Throw", lldb:: eLanguageTypeSwift})
}

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for the detailed suggestions! Makes sense!

For ObjC, just to clarify, the intention of hiding the filters was NOT because the debugger didn't support it - the intention was to avoid clustering/confusing users - that is, if they're not debugging ObjC, there's no reason to show the objc filters. (And we infer this by checking if they're debugging on a mac - it's theoretically possible they're cross debugging objc from a non-mac but in practice I don't think it's likely )
Does this seem reasonable?

Copy link
Collaborator

Choose a reason for hiding this comment

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

The ObjC Language runtime is able to detect whether ObjC is loaded into the program. It runs that detector on each library load, so it keeps an accurate notion of this. Ditto for the swift language runtime. It would be better to consult that than guess based on platform. There may not currently be a way to ask that from the SB API's but we can certainly make one...

Copy link
Member Author

Choose a reason for hiding this comment

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

The ObjC Language runtime is able to detect whether ObjC is loaded into the program. It runs that detector on each library load, so it keeps an accurate notion of this. Ditto for the swift language runtime. It would be better to consult that than guess based on platform.

This code runs before the runtimes (objc/swift) so it probably won't be able to query that, though?

Copy link
Member Author

Choose a reason for hiding this comment

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

P.S: it was pointed out to me that changed capabilities can be pushed as an event. So I guess we could init the list of filters based on whether the languages are supported. Then when the runtime(s) become available, we can update the list after querying for which language is being debugged. WDYT?

Copy link
Collaborator

Choose a reason for hiding this comment

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

ObjC tends to only use exceptions for error reporting, not for message passing, so a lot of ObjC developers leave this breakpoint on all the time. Having to wait till the first load event that brings in ObjC would make that tedious.

Copy link
Member

Choose a reason for hiding this comment

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

Btw, it's possible to register typesystems/languages at initialization via runtime plugins. I think it would be ideal if the breakpoint list could get updated/refreshed after the target has been loaded (maybe at the first stop point)

@adrian-prantl
Copy link
Collaborator

I would be nice if we can detect if we support Swift dynamically. Internally in LLDB, we can ask for a TypeSystem by language using:

See also how lldb/test/Shell/Process/UnsupportedLanguage.test works

for (const auto &exc_bp : g_dap.exception_breakpoints) {
// Skipping objc breakpoint filters if not working on macos.
if (exc_bp.language == lldb::eLanguageTypeObjC &&
triple.find("macos") == std::string::npos) {
Copy link
Member

Choose a reason for hiding this comment

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

In addition to what Jim said above, this might not always work. For example, there are more apple triples (e.g. arm64-apple-ios)

 - added util function for querying whether a language is supported by the type system
 - populate the breakpoint filters table based on the supported language(s)
@oontvoo oontvoo reopened this May 24, 2024
@oontvoo
Copy link
Member Author

oontvoo commented May 24, 2024

I would be nice if we can detect if we support Swift dynamically. Internally in LLDB, we can ask for a TypeSystem by language using:

llvm::Expected<lldb::TypeSystemSP>
TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language,
                                        Module *module, bool can_create);
llvm::Expected<lldb::TypeSystemSP>
TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language,
                                        Target *target, bool can_create);

These functions will return respectively:

TypeSystem::CreateInstance(language, module);
TypeSystem::CreateInstance(language, target);

We should be able to add a new static method to the TypeSystem.h/.cpp that can answer if a language is supported with something like:

static bool TypeSystem::SupportsLanguage(lldb::LanguageType language);

Each TypeSystem plugin can register a new callback that can answer if they support a language. Then we can add a static function on SBDebugger that would expose this function with something like:

static bool SBDebugger::SupportsLanguage(lldb::LanguageType language);

I will make comments in the DAP.cpp where this would be used.

Done!

@oontvoo oontvoo closed this May 24, 2024
@oontvoo oontvoo reopened this May 24, 2024
Comment on lines 343 to 344
LanguageSet plugins =
PluginManager::GetAllTypeSystemSupportedLanguagesForTypes();
Copy link
Member

Choose a reason for hiding this comment

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

s/plugins/languages/

@@ -331,6 +333,7 @@ struct DAP {
// "Content-Length:" field followed by the length, followed by the raw
// JSON bytes.
void SendJSON(const std::string &json_str);
bool bp_initted;
Copy link
Member

Choose a reason for hiding this comment

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

This should be next to exception_breakpoints, but I wouldn't bother with the boolean and instead make exception_breakpoints a std::optional<...> and initialize it in PopulateExceptionBreakpoints so that the two are inherently tied together.

 - use std::optional
 - rename plugins->languages
Copy link
Member

@JDevlieghere JDevlieghere left a comment

Choose a reason for hiding this comment

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

LGTM!

@oontvoo
Copy link
Member Author

oontvoo commented May 28, 2024

@clayborg Hi, do you have any further comments/feedback on this? Thanks!
(If not, I plan to merge this in the next few days)

@oontvoo oontvoo merged commit cfb209b into llvm:main May 29, 2024
5 checks passed
@gulfemsavrun
Copy link
Contributor

gulfemsavrun commented May 29, 2024

We started seeing lldb test failures in TestDAP*.

======================================================================
FAIL: test_commands (TestDAP_launch.TestDAP_launch.test_commands)
    Tests the "initCommands", "preRunCommands", "stopCommands",
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/b/s/w/ir/x/w/llvm-llvm-project/lldb/packages/Python/lldbsuite/test/decorators.py", line 150, in wrapper
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/b/s/w/ir/x/w/llvm-llvm-project/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py", line 324, in test_commands
    self.continue_to_breakpoints(breakpoint_ids)
  File "/b/s/w/ir/x/w/llvm-llvm-project/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py", line 245, in continue_to_breakpoints
    self.verify_breakpoint_hit(breakpoint_ids)
  File "/b/s/w/ir/x/w/llvm-llvm-project/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py", line 99, in verify_breakpoint_hit
    self.assertTrue(False, "breakpoint not hit")
AssertionError: False is not true : breakpoint not hit

https://logs.chromium.org/logs/fuchsia/buildbucket/cr-buildbucket/8746585790559468897/+/u/lldb/test/stdout

gulfemsavrun added a commit that referenced this pull request May 29, 2024
@oontvoo oontvoo mentioned this pull request Jun 6, 2024
oontvoo added a commit that referenced this pull request Jun 7, 2024
Re-apply #87550 with fixes.

Details:
Some tests in fuchsia failed because of the newly added assertion.
This was because `GetExceptionBreakpoint()` could be called before
`g_dap.debugger` was initted.

The fix here is to just lazily populate the list in
GetExceptionBreakpoint() rather than assuming it's already been initted.
(There is some nuisance here because we can't simply just populate it in
DAP::DAP(), which is a global ctor and is called before
`SBDebugger::Initialize()` is called. )
@felipepiovezan
Copy link
Contributor

@felipepiovezan
Copy link
Contributor

Would you mind reverting it until you have a chance to look at the failures?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants