Skip to content

Commit 0adccd1

Browse files
[lldb] Allow languages to filter breakpoints set by line (llvm#83908)
Some languages may create artificial functions that have no real user code, even though there is line table information for them. One such case is with coroutine code that receives the CoroSplitter transformation in LLVM IR. That code transformation creates many different Functions, cloning one Instruction into many Instructions in many different Functions and copying the associated debug locations. It would be difficult to make that pass delete debug locations of cloned instructions in a language agnostic way (is it even possible?), but LLDB can ignore certain locations by querying its Language APIs and having it decide based on, for example, mangling information.
1 parent 22eb800 commit 0adccd1

File tree

5 files changed

+69
-2
lines changed

5 files changed

+69
-2
lines changed

lldb/include/lldb/Target/Language.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@
2626

2727
namespace lldb_private {
2828

29+
class LanguageProperties : public Properties {
30+
public:
31+
LanguageProperties();
32+
33+
static llvm::StringRef GetSettingName();
34+
35+
bool GetEnableFilterForLineBreakpoints() const;
36+
};
37+
2938
class Language : public PluginInterface {
3039
public:
3140
class TypeScavenger {
@@ -324,6 +333,8 @@ class Language : public PluginInterface {
324333
static LanguageSet GetLanguagesSupportingTypeSystemsForExpressions();
325334
static LanguageSet GetLanguagesSupportingREPLs();
326335

336+
static LanguageProperties &GetGlobalLanguageProperties();
337+
327338
// Given a mangled function name, calculates some alternative manglings since
328339
// the compiler mangling may not line up with the symbol we are expecting.
329340
virtual std::vector<ConstString>
@@ -339,6 +350,15 @@ class Language : public PluginInterface {
339350

340351
virtual llvm::StringRef GetInstanceVariableName() { return {}; }
341352

353+
/// Returns true if this SymbolContext should be ignored when setting
354+
/// breakpoints by line (number or regex). Helpful for languages that create
355+
/// artificial functions without meaningful user code associated with them
356+
/// (e.g. code that gets expanded in late compilation stages, like by
357+
/// CoroSplitter).
358+
virtual bool IgnoreForLineBreakpoints(const SymbolContext &) const {
359+
return false;
360+
}
361+
342362
protected:
343363
// Classes that inherit from Language can see and modify these
344364

lldb/source/Breakpoint/BreakpointResolver.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "lldb/Symbol/CompileUnit.h"
2424
#include "lldb/Symbol/Function.h"
2525
#include "lldb/Symbol/SymbolContext.h"
26+
#include "lldb/Target/Language.h"
2627
#include "lldb/Target/Target.h"
2728
#include "lldb/Utility/LLDBLog.h"
2829
#include "lldb/Utility/Log.h"
@@ -203,8 +204,15 @@ void BreakpointResolver::SetSCMatchesByLine(
203204
SearchFilter &filter, SymbolContextList &sc_list, bool skip_prologue,
204205
llvm::StringRef log_ident, uint32_t line, std::optional<uint16_t> column) {
205206
llvm::SmallVector<SymbolContext, 16> all_scs;
206-
for (uint32_t i = 0; i < sc_list.GetSize(); ++i)
207-
all_scs.push_back(sc_list[i]);
207+
208+
for (const auto &sc : sc_list) {
209+
if (Language::GetGlobalLanguageProperties()
210+
.GetEnableFilterForLineBreakpoints())
211+
if (Language *lang = Language::FindPlugin(sc.GetLanguage());
212+
lang && lang->IgnoreForLineBreakpoints(sc))
213+
continue;
214+
all_scs.push_back(sc);
215+
}
208216

209217
while (all_scs.size()) {
210218
uint32_t closest_line = UINT32_MAX;

lldb/source/Core/Debugger.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,9 @@ Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
860860
m_collection_sp->AppendProperty(
861861
"symbols", "Symbol lookup and cache settings.", true,
862862
ModuleList::GetGlobalModuleListProperties().GetValueProperties());
863+
m_collection_sp->AppendProperty(
864+
LanguageProperties::GetSettingName(), "Language settings.", true,
865+
Language::GetGlobalLanguageProperties().GetValueProperties());
863866
if (m_command_interpreter_up) {
864867
m_collection_sp->AppendProperty(
865868
"interpreter",

lldb/source/Target/Language.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "lldb/Target/Language.h"
1414

1515
#include "lldb/Core/PluginManager.h"
16+
#include "lldb/Interpreter/OptionValueProperties.h"
1617
#include "lldb/Symbol/SymbolFile.h"
1718
#include "lldb/Symbol/TypeList.h"
1819
#include "lldb/Target/Target.h"
@@ -27,6 +28,35 @@ using namespace lldb_private::formatters;
2728
typedef std::unique_ptr<Language> LanguageUP;
2829
typedef std::map<lldb::LanguageType, LanguageUP> LanguagesMap;
2930

31+
#define LLDB_PROPERTIES_language
32+
#include "TargetProperties.inc"
33+
34+
enum {
35+
#define LLDB_PROPERTIES_language
36+
#include "TargetPropertiesEnum.inc"
37+
};
38+
39+
LanguageProperties &Language::GetGlobalLanguageProperties() {
40+
static LanguageProperties g_settings;
41+
return g_settings;
42+
}
43+
44+
llvm::StringRef LanguageProperties::GetSettingName() {
45+
static constexpr llvm::StringLiteral g_setting_name("language");
46+
return g_setting_name;
47+
}
48+
49+
LanguageProperties::LanguageProperties() {
50+
m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
51+
m_collection_sp->Initialize(g_language_properties);
52+
}
53+
54+
bool LanguageProperties::GetEnableFilterForLineBreakpoints() const {
55+
const uint32_t idx = ePropertyEnableFilterForLineBreakpoints;
56+
return GetPropertyAtIndexAs<bool>(
57+
idx, g_language_properties[idx].default_uint_value != 0);
58+
}
59+
3060
static LanguagesMap &GetLanguagesMap() {
3161
static LanguagesMap *g_map = nullptr;
3262
static llvm::once_flag g_initialize;

lldb/source/Target/TargetProperties.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,3 +311,9 @@ let Definition = "thread" in {
311311
DefaultUnsignedValue<600000>,
312312
Desc<"Maximum number of frames to backtrace.">;
313313
}
314+
315+
let Definition = "language" in {
316+
def EnableFilterForLineBreakpoints: Property<"enable-filter-for-line-breakpoints", "Boolean">,
317+
DefaultTrue,
318+
Desc<"If true, allow Language plugins to filter locations when setting breakpoints by line number or regex.">;
319+
}

0 commit comments

Comments
 (0)