Skip to content

Commit 06e9b99

Browse files
committed
[lldb][progress] Add discrete boolean flag to progress reports
This commit adds a boolean flag `is_discrete` is to progress reports in LLDB. The flag is set to false by default and indicates if a progress event is discrete, i.e. an operation that has no clear start and end and can happen multiple times during the course of a debug session. Operations that happen in this manner will report multiple individual progress events as they happen, so this flag gives the functionality to group multiple progress events so they can be reported in a less haphazard manner.
1 parent aea94c9 commit 06e9b99

File tree

10 files changed

+88
-28
lines changed

10 files changed

+88
-28
lines changed

lldb/include/lldb/Core/Debugger.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -618,10 +618,16 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
618618
/// debugger identifier that this progress should be delivered to. If this
619619
/// optional parameter does not have a value, the progress will be
620620
/// delivered to all debuggers.
621+
///
622+
/// \param [in] report_type
623+
/// Indicates whether the operation for which this progress reporting is
624+
/// reporting on will happen as an aggregate of multiple individual
625+
/// progress reports or not.
621626
static void ReportProgress(uint64_t progress_id, std::string title,
622627
std::string details, uint64_t completed,
623628
uint64_t total,
624-
std::optional<lldb::user_id_t> debugger_id);
629+
std::optional<lldb::user_id_t> debugger_id,
630+
Progress::ProgressReportType report_type);
625631

626632
static void ReportDiagnosticImpl(DiagnosticEventData::Type type,
627633
std::string message,

lldb/include/lldb/Core/DebuggerEvents.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "lldb/Core/ModuleSpec.h"
10+
#include "lldb/Core/Progress.h"
1011
#include "lldb/Utility/Event.h"
1112
#include "lldb/Utility/StructuredData.h"
1213

@@ -21,10 +22,11 @@ class Stream;
2122
class ProgressEventData : public EventData {
2223
public:
2324
ProgressEventData(uint64_t progress_id, std::string title, std::string update,
24-
uint64_t completed, uint64_t total, bool debugger_specific)
25+
uint64_t completed, uint64_t total, bool debugger_specific,
26+
Progress::ProgressReportType report_type)
2527
: m_title(std::move(title)), m_details(std::move(update)),
2628
m_id(progress_id), m_completed(completed), m_total(total),
27-
m_debugger_specific(debugger_specific) {}
29+
m_debugger_specific(debugger_specific), m_report_type(report_type) {}
2830

2931
static llvm::StringRef GetFlavorString();
3032

@@ -52,6 +54,10 @@ class ProgressEventData : public EventData {
5254
const std::string &GetTitle() const { return m_title; }
5355
const std::string &GetDetails() const { return m_details; }
5456
bool IsDebuggerSpecific() const { return m_debugger_specific; }
57+
bool IsAggregate() const {
58+
return m_report_type ==
59+
Progress::ProgressReportType::eAggregateProgressReport;
60+
}
5561

5662
private:
5763
/// The title of this progress event. The value is expected to remain stable
@@ -68,6 +74,7 @@ class ProgressEventData : public EventData {
6874
uint64_t m_completed;
6975
const uint64_t m_total;
7076
const bool m_debugger_specific;
77+
const Progress::ProgressReportType m_report_type;
7178
ProgressEventData(const ProgressEventData &) = delete;
7279
const ProgressEventData &operator=(const ProgressEventData &) = delete;
7380
};

lldb/include/lldb/Core/Progress.h

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ namespace lldb_private {
5555

5656
class Progress {
5757
public:
58+
/// Enum that indicates the type of progress report
59+
enum class ProgressReportType {
60+
eAggregateProgressReport,
61+
eNonAggregateProgressReport
62+
};
5863
/// Construct a progress object that will report information.
5964
///
6065
/// The constructor will create a unique progress reporting object and
@@ -63,13 +68,30 @@ class Progress {
6368
///
6469
/// @param [in] title The title of this progress activity.
6570
///
66-
/// @param [in] total The total units of work to be done if specified, if
67-
/// set to UINT64_MAX then an indeterminate progress indicator should be
71+
/// @param [in] report_type Enum value indicating how the progress is being
72+
/// reported. Progress reports considered "aggregate" are reports done for
73+
/// operations that may happen multiple times during a debug session.
74+
///
75+
/// For example, when a debug session is first started it needs to parse the
76+
/// symbol tables for all files that were initially included and this
77+
/// operation will deliver progress reports. If new symbol tables need to be
78+
/// parsed later during the session then these will also be parsed and deliver
79+
/// more progress reports. This type of operation would use the
80+
/// eAggregateProgressReport enum. Using this enum would allow these progress
81+
/// reports to be grouped together as one, even though their reports are
82+
/// happening individually.
83+
///
84+
/// @param [in] total Optional total units of work to be done if specified, if
85+
/// unset then an indeterminate progress indicator should be
6886
/// displayed.
6987
///
7088
/// @param [in] debugger An optional debugger pointer to specify that this
7189
/// progress is to be reported only to specific debuggers.
72-
Progress(std::string title, uint64_t total = UINT64_MAX,
90+
///
91+
Progress(std::string title,
92+
ProgressReportType report_type =
93+
ProgressReportType::eNonAggregateProgressReport,
94+
std::optional<uint64_t> total = std::nullopt,
7395
lldb_private::Debugger *debugger = nullptr);
7496

7597
/// Destroy the progress object.
@@ -97,12 +119,17 @@ class Progress {
97119
/// The title of the progress activity.
98120
std::string m_title;
99121
std::mutex m_mutex;
122+
/// Set to eAggregateProgressReport if the progress event is aggregate;
123+
/// meaning it will happen multiple times during a debug session as individual
124+
/// progress events
125+
ProgressReportType m_report_type =
126+
ProgressReportType::eNonAggregateProgressReport;
100127
/// A unique integer identifier for progress reporting.
101128
const uint64_t m_id;
102129
/// How much work ([0...m_total]) that has been completed.
103130
uint64_t m_completed;
104-
/// Total amount of work, UINT64_MAX for non deterministic progress.
105-
const uint64_t m_total;
131+
/// Total amount of work, use a std::nullopt for non deterministic progress.
132+
const std::optional<uint64_t> m_total;
106133
/// The optional debugger ID to report progress to. If this has no value then
107134
/// all debuggers will receive this event.
108135
std::optional<lldb::user_id_t> m_debugger_id;

lldb/source/Core/Debugger.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "lldb/Core/ModuleList.h"
1616
#include "lldb/Core/ModuleSpec.h"
1717
#include "lldb/Core/PluginManager.h"
18+
#include "lldb/Core/Progress.h"
1819
#include "lldb/Core/StreamAsynchronousIO.h"
1920
#include "lldb/DataFormatters/DataVisualization.h"
2021
#include "lldb/Expression/REPL.h"
@@ -1421,22 +1422,24 @@ void Debugger::SetDestroyCallback(
14211422
static void PrivateReportProgress(Debugger &debugger, uint64_t progress_id,
14221423
std::string title, std::string details,
14231424
uint64_t completed, uint64_t total,
1424-
bool is_debugger_specific) {
1425+
bool is_debugger_specific,
1426+
Progress::ProgressReportType report_type) {
14251427
// Only deliver progress events if we have any progress listeners.
14261428
const uint32_t event_type = Debugger::eBroadcastBitProgress;
14271429
if (!debugger.GetBroadcaster().EventTypeHasListeners(event_type))
14281430
return;
14291431
EventSP event_sp(new Event(
1430-
event_type,
1431-
new ProgressEventData(progress_id, std::move(title), std::move(details),
1432-
completed, total, is_debugger_specific)));
1432+
event_type, new ProgressEventData(progress_id, std::move(title),
1433+
std::move(details), completed, total,
1434+
is_debugger_specific, report_type)));
14331435
debugger.GetBroadcaster().BroadcastEvent(event_sp);
14341436
}
14351437

14361438
void Debugger::ReportProgress(uint64_t progress_id, std::string title,
14371439
std::string details, uint64_t completed,
14381440
uint64_t total,
1439-
std::optional<lldb::user_id_t> debugger_id) {
1441+
std::optional<lldb::user_id_t> debugger_id,
1442+
Progress::ProgressReportType report_type) {
14401443
// Check if this progress is for a specific debugger.
14411444
if (debugger_id) {
14421445
// It is debugger specific, grab it and deliver the event if the debugger
@@ -1445,7 +1448,7 @@ void Debugger::ReportProgress(uint64_t progress_id, std::string title,
14451448
if (debugger_sp)
14461449
PrivateReportProgress(*debugger_sp, progress_id, std::move(title),
14471450
std::move(details), completed, total,
1448-
/*is_debugger_specific*/ true);
1451+
/*is_debugger_specific*/ true, report_type);
14491452
return;
14501453
}
14511454
// The progress event is not debugger specific, iterate over all debuggers
@@ -1455,7 +1458,7 @@ void Debugger::ReportProgress(uint64_t progress_id, std::string title,
14551458
DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
14561459
for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos)
14571460
PrivateReportProgress(*(*pos), progress_id, title, details, completed,
1458-
total, /*is_debugger_specific*/ false);
1461+
total, /*is_debugger_specific*/ false, report_type);
14591462
}
14601463
}
14611464

lldb/source/Core/DebuggerEvents.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ ProgressEventData::GetAsStructuredData(const Event *event_ptr) {
6767
dictionary_sp->AddIntegerItem("total", progress_data->GetTotal());
6868
dictionary_sp->AddBooleanItem("debugger_specific",
6969
progress_data->IsDebuggerSpecific());
70+
dictionary_sp->AddBooleanItem("is_aggregate", progress_data->IsAggregate());
7071

7172
return dictionary_sp;
7273
}

lldb/source/Core/Progress.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,18 @@
1111
#include "lldb/Core/Debugger.h"
1212
#include "lldb/Utility/StreamString.h"
1313

14+
#include <optional>
15+
1416
using namespace lldb;
1517
using namespace lldb_private;
1618

1719
std::atomic<uint64_t> Progress::g_id(0);
1820

19-
Progress::Progress(std::string title, uint64_t total,
21+
Progress::Progress(std::string title, ProgressReportType report_type,
22+
std::optional<uint64_t> total,
2023
lldb_private::Debugger *debugger)
21-
: m_title(title), m_id(++g_id), m_completed(0), m_total(total) {
24+
: m_title(title), m_report_type(report_type), m_id(++g_id), m_completed(0),
25+
m_total(total) {
2226
assert(total > 0);
2327
if (debugger)
2428
m_debugger_id = debugger->GetID();
@@ -31,7 +35,7 @@ Progress::~Progress() {
3135
// destructed so it indicates the progress dialog/activity should go away.
3236
std::lock_guard<std::mutex> guard(m_mutex);
3337
if (!m_completed)
34-
m_completed = m_total;
38+
m_completed = m_total.value();
3539
ReportProgress();
3640
}
3741

@@ -40,8 +44,8 @@ void Progress::Increment(uint64_t amount, std::string update) {
4044
std::lock_guard<std::mutex> guard(m_mutex);
4145
// Watch out for unsigned overflow and make sure we don't increment too
4246
// much and exceed m_total.
43-
if (amount > (m_total - m_completed))
44-
m_completed = m_total;
47+
if (amount > (m_total.value() - m_completed))
48+
m_completed = m_total.value();
4549
else
4650
m_completed += amount;
4751
ReportProgress(update);
@@ -52,8 +56,8 @@ void Progress::ReportProgress(std::string update) {
5256
if (!m_complete) {
5357
// Make sure we only send one notification that indicates the progress is
5458
// complete.
55-
m_complete = m_completed == m_total;
59+
m_complete = m_completed == m_total.value();
5660
Debugger::ReportProgress(m_id, m_title, std::move(update), m_completed,
57-
m_total, m_debugger_id);
61+
m_total.value(), m_debugger_id, m_report_type);
5862
}
5963
}

lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2225,7 +2225,8 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
22252225
const char *file_name = file.GetFilename().AsCString("<Unknown>");
22262226
LLDB_SCOPED_TIMERF("ObjectFileMachO::ParseSymtab () module = %s", file_name);
22272227
LLDB_LOG(log, "Parsing symbol table for {0}", file_name);
2228-
Progress progress(llvm::formatv("Parsing symbol table for {0}", file_name));
2228+
Progress progress(llvm::formatv("Parsing symbol table for {0}", file_name),
2229+
Progress::ProgressReportType::eAggregateProgressReport);
22292230

22302231
llvm::MachO::symtab_command symtab_load_command = {0, 0, 0, 0, 0, 0};
22312232
llvm::MachO::linkedit_data_command function_starts_load_command = {0, 0, 0, 0};

lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ void ManualDWARFIndex::Index() {
7777
const uint64_t total_progress = units_to_index.size() * 2 + 8;
7878
Progress progress(
7979
llvm::formatv("Manually indexing DWARF for {0}", module_desc.GetData()),
80-
total_progress);
80+
Progress::ProgressReportType::eAggregateProgressReport, total_progress);
8181

8282
std::vector<IndexSet> sets(units_to_index.size());
8383

lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,8 @@ void SymbolFileDWARF::InitializeObject() {
472472
if (apple_names.GetByteSize() > 0 || apple_namespaces.GetByteSize() > 0 ||
473473
apple_types.GetByteSize() > 0 || apple_objc.GetByteSize() > 0) {
474474
Progress progress(llvm::formatv("Loading Apple DWARF index for {0}",
475-
module_desc.GetData()));
475+
module_desc.GetData()),
476+
Progress::ProgressReportType::eAggregateProgressReport);
476477
m_index = AppleDWARFIndex::Create(
477478
*GetObjectFile()->GetModule(), apple_names, apple_namespaces,
478479
apple_types, apple_objc, m_context.getOrLoadStrData());
@@ -485,7 +486,8 @@ void SymbolFileDWARF::InitializeObject() {
485486
LoadSectionData(eSectionTypeDWARFDebugNames, debug_names);
486487
if (debug_names.GetByteSize() > 0) {
487488
Progress progress(
488-
llvm::formatv("Loading DWARF5 index for {0}", module_desc.GetData()));
489+
llvm::formatv("Loading DWARF5 index for {0}", module_desc.GetData()),
490+
Progress::ProgressReportType::eAggregateProgressReport);
489491
llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>> index_or =
490492
DebugNamesDWARFIndex::Create(*GetObjectFile()->GetModule(),
491493
debug_names,

lldb/test/API/functionalities/progress_reporting/TestProgressReporting.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,14 @@ def test_dwarf_symbol_loading_progress_report_structured_data(self):
3737

3838
event = lldbutil.fetch_next_event(self, self.listener, self.broadcaster)
3939
progress_data = lldb.SBDebugger.GetProgressDataFromEvent(event)
40-
message = progress_data.GetValueForKey("message").GetStringValue(100)
41-
self.assertGreater(len(message), 0)
40+
title = progress_data.GetValueForKey("title").GetStringValue(100)
41+
self.assertGreater(len(title), 0)
42+
43+
is_aggregate = progress_data.GetValueForKey("is_aggregate")
44+
self.assertTrue(
45+
is_aggregate.IsValid(),
46+
"ProgressEventData key 'is_aggregate' does not exist.",
47+
)
48+
self.assertTrue(
49+
is_aggregate, "ProgressEventData key 'is_aggregate' should be true."
50+
)

0 commit comments

Comments
 (0)