mirror of
https://github.com/intel/llvm.git
synced 2026-01-23 07:58:23 +08:00
Reapply PR/87550 (#94625)
Re-apply https://github.com/llvm/llvm-project/pull/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. )
This commit is contained in:
@@ -57,6 +57,8 @@ public:
|
||||
|
||||
static const char *GetBroadcasterClass();
|
||||
|
||||
static bool SupportsLanguage(lldb::LanguageType language);
|
||||
|
||||
lldb::SBBroadcaster GetBroadcaster();
|
||||
|
||||
/// Get progress data from a SBEvent whose type is eBroadcastBitProgress.
|
||||
|
||||
@@ -209,6 +209,7 @@ public:
|
||||
// TypeSystems can support more than one language
|
||||
virtual bool SupportsLanguage(lldb::LanguageType language) = 0;
|
||||
|
||||
static bool SupportsLanguageStatic(lldb::LanguageType language);
|
||||
// Type Completion
|
||||
|
||||
virtual bool GetCompleteType(lldb::opaque_compiler_type_t type) = 0;
|
||||
|
||||
@@ -1742,3 +1742,7 @@ bool SBDebugger::InterruptRequested() {
|
||||
return m_opaque_sp->InterruptRequested();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SBDebugger::SupportsLanguage(lldb::LanguageType language) {
|
||||
return TypeSystem::SupportsLanguageStatic(language);
|
||||
}
|
||||
|
||||
@@ -335,3 +335,14 @@ TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language,
|
||||
}
|
||||
return GetTypeSystemForLanguage(language);
|
||||
}
|
||||
|
||||
bool TypeSystem::SupportsLanguageStatic(lldb::LanguageType language) {
|
||||
if (language == eLanguageTypeUnknown)
|
||||
return false;
|
||||
|
||||
LanguageSet languages =
|
||||
PluginManager::GetAllTypeSystemSupportedLanguagesForTypes();
|
||||
if (languages.Empty())
|
||||
return false;
|
||||
return languages[language];
|
||||
}
|
||||
|
||||
@@ -32,14 +32,7 @@ namespace lldb_dap {
|
||||
DAP g_dap;
|
||||
|
||||
DAP::DAP()
|
||||
: broadcaster("lldb-dap"),
|
||||
exception_breakpoints(
|
||||
{{"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}}),
|
||||
: broadcaster("lldb-dap"), exception_breakpoints(),
|
||||
focus_tid(LLDB_INVALID_THREAD_ID), stop_at_entry(false), is_attach(false),
|
||||
enable_auto_variable_summaries(false),
|
||||
enable_synthetic_child_debugging(false),
|
||||
@@ -65,8 +58,51 @@ DAP::DAP()
|
||||
|
||||
DAP::~DAP() = default;
|
||||
|
||||
void DAP::PopulateExceptionBreakpoints() {
|
||||
llvm::call_once(initExceptionBreakpoints, [this]() {
|
||||
exception_breakpoints = {};
|
||||
if (lldb::SBDebugger::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 (lldb::SBDebugger::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 (lldb::SBDebugger::SupportsLanguage(lldb::eLanguageTypeSwift)) {
|
||||
exception_breakpoints->emplace_back("swift_catch", "Swift Catch",
|
||||
lldb::eLanguageTypeSwift);
|
||||
exception_breakpoints->emplace_back("swift_throw", "Swift Throw",
|
||||
lldb::eLanguageTypeSwift);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ExceptionBreakpoint *DAP::GetExceptionBreakpoint(const std::string &filter) {
|
||||
for (auto &bp : exception_breakpoints) {
|
||||
// PopulateExceptionBreakpoints() is called after g_dap.debugger is created
|
||||
// in a request-initialize.
|
||||
//
|
||||
// But this GetExceptionBreakpoint() method may be called before attaching, in
|
||||
// which case, we may not have populated the filter yet.
|
||||
//
|
||||
// We also cannot call PopulateExceptionBreakpoints() in DAP::DAP() because
|
||||
// we need SBDebugger::Initialize() to have been called before this.
|
||||
//
|
||||
// So just calling PopulateExceptionBreakoints(),which does lazy-populating
|
||||
// seems easiest. Two other options include:
|
||||
// + call g_dap.PopulateExceptionBreakpoints() in lldb-dap.cpp::main()
|
||||
// right after the call to SBDebugger::Initialize()
|
||||
// + Just call PopulateExceptionBreakpoints() to get a fresh list everytime
|
||||
// we query (a bit overkill since it's not likely to change?)
|
||||
PopulateExceptionBreakpoints();
|
||||
assert(exception_breakpoints.has_value() &&
|
||||
"exception_breakpoints must have been populated");
|
||||
|
||||
for (auto &bp : *exception_breakpoints) {
|
||||
if (bp.filter == filter)
|
||||
return &bp;
|
||||
}
|
||||
@@ -74,7 +110,12 @@ ExceptionBreakpoint *DAP::GetExceptionBreakpoint(const std::string &filter) {
|
||||
}
|
||||
|
||||
ExceptionBreakpoint *DAP::GetExceptionBreakpoint(const lldb::break_id_t bp_id) {
|
||||
for (auto &bp : exception_breakpoints) {
|
||||
// See comment in the other GetExceptionBreakpoint().
|
||||
PopulateExceptionBreakpoints();
|
||||
assert(exception_breakpoints.has_value() &&
|
||||
"exception_breakpoints must have been populated");
|
||||
|
||||
for (auto &bp : *exception_breakpoints) {
|
||||
if (bp.bp.GetID() == bp_id)
|
||||
return &bp;
|
||||
}
|
||||
|
||||
@@ -156,7 +156,8 @@ struct DAP {
|
||||
std::unique_ptr<std::ofstream> log;
|
||||
llvm::StringMap<SourceBreakpointMap> source_breakpoints;
|
||||
FunctionBreakpointMap function_breakpoints;
|
||||
std::vector<ExceptionBreakpoint> exception_breakpoints;
|
||||
std::optional<std::vector<ExceptionBreakpoint>> exception_breakpoints;
|
||||
llvm::once_flag initExceptionBreakpoints;
|
||||
std::vector<std::string> init_commands;
|
||||
std::vector<std::string> pre_run_commands;
|
||||
std::vector<std::string> post_run_commands;
|
||||
@@ -228,6 +229,8 @@ struct DAP {
|
||||
|
||||
llvm::json::Value CreateTopLevelScopes();
|
||||
|
||||
void PopulateExceptionBreakpoints();
|
||||
|
||||
/// \return
|
||||
/// Attempt to determine if an expression is a variable expression or
|
||||
/// lldb command using a hueristic based on the first term of the
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <optional>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#if defined(_WIN32)
|
||||
@@ -1586,6 +1587,7 @@ void request_initialize(const llvm::json::Object &request) {
|
||||
bool source_init_file = GetBoolean(arguments, "sourceInitFile", true);
|
||||
|
||||
g_dap.debugger = lldb::SBDebugger::Create(source_init_file, log_cb, nullptr);
|
||||
g_dap.PopulateExceptionBreakpoints();
|
||||
auto cmd = g_dap.debugger.GetCommandInterpreter().AddMultiwordCommand(
|
||||
"lldb-dap", "Commands for managing lldb-dap.");
|
||||
if (GetBoolean(arguments, "supportsStartDebuggingRequest", false)) {
|
||||
@@ -1621,7 +1623,7 @@ 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;
|
||||
for (const auto &exc_bp : g_dap.exception_breakpoints) {
|
||||
for (const auto &exc_bp : *g_dap.exception_breakpoints) {
|
||||
filters.emplace_back(CreateExceptionBreakpointFilter(exc_bp));
|
||||
}
|
||||
body.try_emplace("exceptionBreakpointFilters", std::move(filters));
|
||||
@@ -2476,7 +2478,7 @@ void request_setExceptionBreakpoints(const llvm::json::Object &request) {
|
||||
// Keep a list of any exception breakpoint filter names that weren't set
|
||||
// so we can clear any exception breakpoints if needed.
|
||||
std::set<std::string> unset_filters;
|
||||
for (const auto &bp : g_dap.exception_breakpoints)
|
||||
for (const auto &bp : *g_dap.exception_breakpoints)
|
||||
unset_filters.insert(bp.filter);
|
||||
|
||||
for (const auto &value : *filters) {
|
||||
|
||||
Reference in New Issue
Block a user