2021-10-20 14:49:09 -07:00
|
|
|
//===-- Statistics.cpp ----------------------------------------------------===//
|
|
|
|
|
//
|
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
|
//
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
|
|
#include "lldb/Target/Statistics.h"
|
|
|
|
|
|
|
|
|
|
#include "lldb/Core/Debugger.h"
|
|
|
|
|
#include "lldb/Core/Module.h"
|
2024-02-05 13:17:29 -08:00
|
|
|
#include "lldb/Interpreter/CommandInterpreter.h"
|
2021-10-20 14:49:09 -07:00
|
|
|
#include "lldb/Symbol/SymbolFile.h"
|
2024-02-06 19:47:34 -05:00
|
|
|
#include "lldb/Target/DynamicLoader.h"
|
2021-10-27 18:33:17 -07:00
|
|
|
#include "lldb/Target/Process.h"
|
2021-10-20 14:49:09 -07:00
|
|
|
#include "lldb/Target/Target.h"
|
2021-10-27 18:33:17 -07:00
|
|
|
#include "lldb/Target/UnixSignals.h"
|
2021-10-20 14:49:09 -07:00
|
|
|
|
|
|
|
|
using namespace lldb;
|
|
|
|
|
using namespace lldb_private;
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
2021-10-21 16:01:00 -07:00
|
|
|
static void EmplaceSafeString(llvm::json::Object &obj, llvm::StringRef key,
|
|
|
|
|
const std::string &str) {
|
|
|
|
|
if (str.empty())
|
|
|
|
|
return;
|
|
|
|
|
if (LLVM_LIKELY(llvm::json::isUTF8(str)))
|
|
|
|
|
obj.try_emplace(key, str);
|
|
|
|
|
else
|
|
|
|
|
obj.try_emplace(key, llvm::json::fixUTF8(str));
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-20 14:49:09 -07:00
|
|
|
json::Value StatsSuccessFail::ToJSON() const {
|
|
|
|
|
return json::Object{{"successes", successes}, {"failures", failures}};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static double elapsed(const StatsTimepoint &start, const StatsTimepoint &end) {
|
2022-01-17 15:04:30 +01:00
|
|
|
StatsDuration::Duration elapsed =
|
|
|
|
|
end.time_since_epoch() - start.time_since_epoch();
|
2021-10-20 14:49:09 -07:00
|
|
|
return elapsed.count();
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-21 16:01:00 -07:00
|
|
|
void TargetStats::CollectStats(Target &target) {
|
|
|
|
|
m_module_identifiers.clear();
|
|
|
|
|
for (ModuleSP module_sp : target.GetImages().Modules())
|
|
|
|
|
m_module_identifiers.emplace_back((intptr_t)module_sp.get());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
json::Value ModuleStats::ToJSON() const {
|
|
|
|
|
json::Object module;
|
|
|
|
|
EmplaceSafeString(module, "path", path);
|
|
|
|
|
EmplaceSafeString(module, "uuid", uuid);
|
|
|
|
|
EmplaceSafeString(module, "triple", triple);
|
|
|
|
|
module.try_emplace("identifier", identifier);
|
|
|
|
|
module.try_emplace("symbolTableParseTime", symtab_parse_time);
|
|
|
|
|
module.try_emplace("symbolTableIndexTime", symtab_index_time);
|
2021-12-28 10:49:59 -08:00
|
|
|
module.try_emplace("symbolTableLoadedFromCache", symtab_loaded_from_cache);
|
|
|
|
|
module.try_emplace("symbolTableSavedToCache", symtab_saved_to_cache);
|
2021-10-25 18:03:06 -07:00
|
|
|
module.try_emplace("debugInfoParseTime", debug_parse_time);
|
|
|
|
|
module.try_emplace("debugInfoIndexTime", debug_index_time);
|
|
|
|
|
module.try_emplace("debugInfoByteSize", (int64_t)debug_info_size);
|
2021-12-28 10:49:59 -08:00
|
|
|
module.try_emplace("debugInfoIndexLoadedFromCache",
|
|
|
|
|
debug_info_index_loaded_from_cache);
|
|
|
|
|
module.try_emplace("debugInfoIndexSavedToCache",
|
|
|
|
|
debug_info_index_saved_to_cache);
|
2022-04-20 07:30:53 -07:00
|
|
|
module.try_emplace("debugInfoEnabled", debug_info_enabled);
|
2022-09-22 17:54:06 -07:00
|
|
|
module.try_emplace("debugInfoHadVariableErrors",
|
|
|
|
|
debug_info_had_variable_errors);
|
2022-11-23 20:28:03 -08:00
|
|
|
module.try_emplace("debugInfoHadIncompleteTypes",
|
|
|
|
|
debug_info_had_incomplete_types);
|
2022-04-20 07:30:53 -07:00
|
|
|
module.try_emplace("symbolTableStripped", symtab_stripped);
|
Fix a double debug info size counting in top level stats for "statistics dump".
This mainly affects Darwin targets (macOS, iOS, tvOS and watchOS) when these targets don't use dSYM files and the debug info was in the .o files. All modules, including the .o files that are loaded by the debug maps, were in the global module list. This was great because it allows us to see each .o file and how much it contributes. There were virtual functions on the SymbolFile class to fetch the symtab/debug info parse and index times, and also the total debug info size. So the main executable would add all of the .o file's stats together and report them as its own data. Then the "totalDebugInfoSize" and many other "totalXXX" top level totals were all being added together. This stems from the fact that my original patch only emitted the modules for a target at the start of the patch, but as comments from the reviews came in, we switched to emitting all of the modules from the global module list.
So this patch fixes it so when we have a SymbolFileDWARFDebugMap that loads .o files, the main executable will have no debug info size or symtab/debug info parse/index times, but each .o file will have its own data as a separate module. Also, to be able to tell when/if we have a dSYM file I have added a "symbolFilePath" if the SymbolFile for the main modules path doesn't match that of the main executable. We also include a "symbolFileModuleIdentifiers" key in each module if the module does have multiple lldb_private::Module objects that contain debug info so that you can track down the information for a module and add up the contributions of all of the .o files.
Tests were added that are labeled with @skipUnlessDarwin and @no_debug_info_test that test all of this functionality so it doesn't regress.
For a module with a dSYM file, we can see the "symbolFilePath" is included:
```
"modules": [
{
"debugInfoByteSize": 1070,
"debugInfoIndexLoadedFromCache": false,
"debugInfoIndexSavedToCache": false,
"debugInfoIndexTime": 0,
"debugInfoParseTime": 0,
"identifier": 4873280600,
"path": "/Users/gclayton/Documents/src/lldb/main/Debug/lldb-test-build.noindex/commands/statistics/basic/TestStats.test_dsym_binary_has_symfile_in_stats/a.out",
"symbolFilePath": "/Users/gclayton/Documents/src/lldb/main/Debug/lldb-test-build.noindex/commands/statistics/basic/TestStats.test_dsym_binary_has_symfile_in_stats/a.out.dSYM/Contents/Resources/DWARF/a.out",
"symbolTableIndexTime": 7.9999999999999996e-06,
"symbolTableLoadedFromCache": false,
"symbolTableParseTime": 7.8999999999999996e-05,
"symbolTableSavedToCache": false,
"triple": "arm64-apple-macosx12.0.0",
"uuid": "E1F7D85B-3A42-321E-BF0D-29B103F5F2E3"
},
```
And for the DWARF in .o file case we can see the "symbolFileModuleIdentifiers" in the executable's module stats:
```
"modules": [
{
"debugInfoByteSize": 0,
"debugInfoIndexLoadedFromCache": false,
"debugInfoIndexSavedToCache": false,
"debugInfoIndexTime": 0,
"debugInfoParseTime": 0,
"identifier": 4603526968,
"path": "/Users/gclayton/Documents/src/lldb/main/Debug/lldb-test-build.noindex/commands/statistics/basic/TestStats.test_no_dsym_binary_has_symfile_identifiers_in_stats/a.out",
"symbolFileModuleIdentifiers": [
4604429832
],
"symbolTableIndexTime": 7.9999999999999996e-06,
"symbolTableLoadedFromCache": false,
"symbolTableParseTime": 0.000112,
"symbolTableSavedToCache": false,
"triple": "arm64-apple-macosx12.0.0",
"uuid": "57008BF5-A726-3DE9-B1BF-3A9AD3EE8569"
},
```
And the .o file for 4604429832 looks like:
```
{
"debugInfoByteSize": 1028,
"debugInfoIndexLoadedFromCache": false,
"debugInfoIndexSavedToCache": false,
"debugInfoIndexTime": 0,
"debugInfoParseTime": 6.0999999999999999e-05,
"identifier": 4604429832,
"path": "/Users/gclayton/Documents/src/lldb/main/Debug/lldb-test-build.noindex/commands/statistics/basic/TestStats.test_no_dsym_binary_has_symfile_identifiers_in_stats/main.o",
"symbolTableIndexTime": 0,
"symbolTableLoadedFromCache": false,
"symbolTableParseTime": 0,
"symbolTableSavedToCache": false,
"triple": "arm64-apple-macosx"
}
```
Differential Revision: https://reviews.llvm.org/D119400
2022-02-09 18:48:17 -08:00
|
|
|
if (!symfile_path.empty())
|
|
|
|
|
module.try_emplace("symbolFilePath", symfile_path);
|
|
|
|
|
|
|
|
|
|
if (!symfile_modules.empty()) {
|
|
|
|
|
json::Array symfile_ids;
|
|
|
|
|
for (const auto symfile_id: symfile_modules)
|
|
|
|
|
symfile_ids.emplace_back(symfile_id);
|
|
|
|
|
module.try_emplace("symbolFileModuleIdentifiers", std::move(symfile_ids));
|
|
|
|
|
}
|
2022-10-31 14:50:04 -07:00
|
|
|
|
|
|
|
|
if (!type_system_stats.empty()) {
|
|
|
|
|
json::Array type_systems;
|
|
|
|
|
for (const auto &entry : type_system_stats) {
|
|
|
|
|
json::Object obj;
|
|
|
|
|
obj.try_emplace(entry.first().str(), entry.second);
|
|
|
|
|
type_systems.emplace_back(std::move(obj));
|
|
|
|
|
}
|
|
|
|
|
module.try_emplace("typeSystemInfo", std::move(type_systems));
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-21 16:01:00 -07:00
|
|
|
return module;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-24 15:12:18 -08:00
|
|
|
llvm::json::Value ConstStringStats::ToJSON() const {
|
|
|
|
|
json::Object obj;
|
|
|
|
|
obj.try_emplace<int64_t>("bytesTotal", stats.GetBytesTotal());
|
|
|
|
|
obj.try_emplace<int64_t>("bytesUsed", stats.GetBytesUsed());
|
|
|
|
|
obj.try_emplace<int64_t>("bytesUnused", stats.GetBytesUnused());
|
|
|
|
|
return obj;
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-06 19:47:34 -05:00
|
|
|
json::Value
|
|
|
|
|
TargetStats::ToJSON(Target &target,
|
|
|
|
|
const lldb_private::StatisticsOptions &options) {
|
|
|
|
|
json::Object target_metrics_json;
|
|
|
|
|
ProcessSP process_sp = target.GetProcessSP();
|
|
|
|
|
const bool summary_only = options.summary_only;
|
|
|
|
|
if (!summary_only) {
|
|
|
|
|
CollectStats(target);
|
2021-10-21 16:01:00 -07:00
|
|
|
|
2024-02-06 19:47:34 -05:00
|
|
|
json::Array json_module_uuid_array;
|
|
|
|
|
for (auto module_identifier : m_module_identifiers)
|
|
|
|
|
json_module_uuid_array.emplace_back(module_identifier);
|
2021-10-21 16:01:00 -07:00
|
|
|
|
2024-02-06 19:47:34 -05:00
|
|
|
target_metrics_json.try_emplace(m_expr_eval.name, m_expr_eval.ToJSON());
|
|
|
|
|
target_metrics_json.try_emplace(m_frame_var.name, m_frame_var.ToJSON());
|
|
|
|
|
target_metrics_json.try_emplace("moduleIdentifiers",
|
|
|
|
|
std::move(json_module_uuid_array));
|
2021-10-21 16:01:00 -07:00
|
|
|
|
2024-02-06 19:47:34 -05:00
|
|
|
if (m_launch_or_attach_time && m_first_private_stop_time) {
|
|
|
|
|
double elapsed_time =
|
|
|
|
|
elapsed(*m_launch_or_attach_time, *m_first_private_stop_time);
|
|
|
|
|
target_metrics_json.try_emplace("launchOrAttachTime", elapsed_time);
|
|
|
|
|
}
|
|
|
|
|
if (m_launch_or_attach_time && m_first_public_stop_time) {
|
|
|
|
|
double elapsed_time =
|
|
|
|
|
elapsed(*m_launch_or_attach_time, *m_first_public_stop_time);
|
|
|
|
|
target_metrics_json.try_emplace("firstStopTime", elapsed_time);
|
|
|
|
|
}
|
|
|
|
|
target_metrics_json.try_emplace("targetCreateTime",
|
|
|
|
|
m_create_time.get().count());
|
|
|
|
|
|
|
|
|
|
json::Array breakpoints_array;
|
|
|
|
|
double totalBreakpointResolveTime = 0.0;
|
|
|
|
|
// Report both the normal breakpoint list and the internal breakpoint list.
|
|
|
|
|
for (int i = 0; i < 2; ++i) {
|
|
|
|
|
BreakpointList &breakpoints = target.GetBreakpointList(i == 1);
|
|
|
|
|
std::unique_lock<std::recursive_mutex> lock;
|
|
|
|
|
breakpoints.GetListMutex(lock);
|
|
|
|
|
size_t num_breakpoints = breakpoints.GetSize();
|
|
|
|
|
for (size_t i = 0; i < num_breakpoints; i++) {
|
|
|
|
|
Breakpoint *bp = breakpoints.GetBreakpointAtIndex(i).get();
|
|
|
|
|
breakpoints_array.push_back(bp->GetStatistics());
|
|
|
|
|
totalBreakpointResolveTime += bp->GetResolveTime().count();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
target_metrics_json.try_emplace("breakpoints",
|
|
|
|
|
std::move(breakpoints_array));
|
|
|
|
|
target_metrics_json.try_emplace("totalBreakpointResolveTime",
|
|
|
|
|
totalBreakpointResolveTime);
|
|
|
|
|
|
|
|
|
|
if (process_sp) {
|
|
|
|
|
UnixSignalsSP unix_signals_sp = process_sp->GetUnixSignals();
|
|
|
|
|
if (unix_signals_sp)
|
|
|
|
|
target_metrics_json.try_emplace(
|
|
|
|
|
"signals", unix_signals_sp->GetHitCountStatistics());
|
|
|
|
|
}
|
2021-10-20 14:49:09 -07:00
|
|
|
}
|
2024-02-06 19:47:34 -05:00
|
|
|
|
|
|
|
|
// Counting "totalSharedLibraryEventHitCount" from breakpoints of kind
|
|
|
|
|
// "shared-library-event".
|
|
|
|
|
{
|
|
|
|
|
uint32_t shared_library_event_breakpoint_hit_count = 0;
|
|
|
|
|
// The "shared-library-event" is only found in the internal breakpoint list.
|
|
|
|
|
BreakpointList &breakpoints = target.GetBreakpointList(/* internal */ true);
|
2021-10-26 17:48:42 -07:00
|
|
|
std::unique_lock<std::recursive_mutex> lock;
|
|
|
|
|
breakpoints.GetListMutex(lock);
|
|
|
|
|
size_t num_breakpoints = breakpoints.GetSize();
|
|
|
|
|
for (size_t i = 0; i < num_breakpoints; i++) {
|
|
|
|
|
Breakpoint *bp = breakpoints.GetBreakpointAtIndex(i).get();
|
2024-02-06 19:47:34 -05:00
|
|
|
if (strcmp(bp->GetBreakpointKind(), "shared-library-event") == 0)
|
|
|
|
|
shared_library_event_breakpoint_hit_count += bp->GetHitCount();
|
2021-10-26 17:48:42 -07:00
|
|
|
}
|
2024-02-06 19:47:34 -05:00
|
|
|
|
|
|
|
|
target_metrics_json.try_emplace("totalSharedLibraryEventHitCount",
|
|
|
|
|
shared_library_event_breakpoint_hit_count);
|
2021-10-26 17:48:42 -07:00
|
|
|
}
|
|
|
|
|
|
2021-10-27 18:33:17 -07:00
|
|
|
if (process_sp) {
|
2021-11-12 15:26:27 -08:00
|
|
|
uint32_t stop_id = process_sp->GetStopID();
|
|
|
|
|
target_metrics_json.try_emplace("stopCount", stop_id);
|
2021-10-26 17:48:42 -07:00
|
|
|
|
2024-02-06 19:47:34 -05:00
|
|
|
llvm::StringRef dyld_plugin_name;
|
|
|
|
|
if (process_sp->GetDynamicLoader())
|
|
|
|
|
dyld_plugin_name = process_sp->GetDynamicLoader()->GetPluginName();
|
|
|
|
|
target_metrics_json.try_emplace("dyldPluginName", dyld_plugin_name);
|
|
|
|
|
}
|
|
|
|
|
target_metrics_json.try_emplace("sourceMapDeduceCount",
|
|
|
|
|
m_source_map_deduce_count);
|
2021-10-20 14:49:09 -07:00
|
|
|
return target_metrics_json;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TargetStats::SetLaunchOrAttachTime() {
|
|
|
|
|
m_launch_or_attach_time = StatsClock::now();
|
2022-12-04 16:51:25 -08:00
|
|
|
m_first_private_stop_time = std::nullopt;
|
2021-10-20 14:49:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TargetStats::SetFirstPrivateStopTime() {
|
|
|
|
|
// Launching and attaching has many paths depending on if synchronous mode
|
|
|
|
|
// was used or if we are stopping at the entry point or not. Only set the
|
|
|
|
|
// first stop time if it hasn't already been set.
|
|
|
|
|
if (!m_first_private_stop_time)
|
|
|
|
|
m_first_private_stop_time = StatsClock::now();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TargetStats::SetFirstPublicStopTime() {
|
|
|
|
|
// Launching and attaching has many paths depending on if synchronous mode
|
|
|
|
|
// was used or if we are stopping at the entry point or not. Only set the
|
|
|
|
|
// first stop time if it hasn't already been set.
|
|
|
|
|
if (!m_first_public_stop_time)
|
|
|
|
|
m_first_public_stop_time = StatsClock::now();
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-22 14:32:35 -07:00
|
|
|
void TargetStats::IncreaseSourceMapDeduceCount() {
|
|
|
|
|
++m_source_map_deduce_count;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-20 14:49:09 -07:00
|
|
|
bool DebuggerStats::g_collecting_stats = false;
|
|
|
|
|
|
2024-02-06 19:47:34 -05:00
|
|
|
llvm::json::Value DebuggerStats::ReportStatistics(
|
|
|
|
|
Debugger &debugger, Target *target,
|
|
|
|
|
const lldb_private::StatisticsOptions &options) {
|
|
|
|
|
|
|
|
|
|
const bool summary_only = options.summary_only;
|
2024-02-19 00:33:23 -05:00
|
|
|
const bool load_all_debug_info = options.load_all_debug_info;
|
2024-02-06 19:47:34 -05:00
|
|
|
|
2021-10-21 16:01:00 -07:00
|
|
|
json::Array json_targets;
|
|
|
|
|
json::Array json_modules;
|
|
|
|
|
double symtab_parse_time = 0.0;
|
|
|
|
|
double symtab_index_time = 0.0;
|
2021-10-25 18:03:06 -07:00
|
|
|
double debug_parse_time = 0.0;
|
|
|
|
|
double debug_index_time = 0.0;
|
2021-12-28 10:49:59 -08:00
|
|
|
uint32_t symtabs_loaded = 0;
|
|
|
|
|
uint32_t symtabs_saved = 0;
|
|
|
|
|
uint32_t debug_index_loaded = 0;
|
|
|
|
|
uint32_t debug_index_saved = 0;
|
2021-10-25 18:03:06 -07:00
|
|
|
uint64_t debug_info_size = 0;
|
2024-02-06 19:47:34 -05:00
|
|
|
|
2021-10-21 16:01:00 -07:00
|
|
|
std::vector<ModuleStats> modules;
|
|
|
|
|
std::lock_guard<std::recursive_mutex> guard(
|
|
|
|
|
Module::GetAllocationModuleCollectionMutex());
|
2022-04-20 07:30:53 -07:00
|
|
|
const uint64_t num_modules = Module::GetNumberAllocatedModules();
|
|
|
|
|
uint32_t num_debug_info_enabled_modules = 0;
|
|
|
|
|
uint32_t num_modules_has_debug_info = 0;
|
2022-11-20 09:40:23 -08:00
|
|
|
uint32_t num_modules_with_variable_errors = 0;
|
2022-11-23 20:28:03 -08:00
|
|
|
uint32_t num_modules_with_incomplete_types = 0;
|
2022-04-20 07:30:53 -07:00
|
|
|
uint32_t num_stripped_modules = 0;
|
2021-10-21 16:01:00 -07:00
|
|
|
for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
|
|
|
|
|
Module *module = Module::GetAllocatedModuleAtIndex(image_idx);
|
|
|
|
|
ModuleStats module_stat;
|
2022-01-17 15:04:30 +01:00
|
|
|
module_stat.symtab_parse_time = module->GetSymtabParseTime().get().count();
|
|
|
|
|
module_stat.symtab_index_time = module->GetSymtabIndexTime().get().count();
|
2021-12-28 10:49:59 -08:00
|
|
|
Symtab *symtab = module->GetSymtab();
|
|
|
|
|
if (symtab) {
|
|
|
|
|
module_stat.symtab_loaded_from_cache = symtab->GetWasLoadedFromCache();
|
|
|
|
|
if (module_stat.symtab_loaded_from_cache)
|
|
|
|
|
++symtabs_loaded;
|
|
|
|
|
module_stat.symtab_saved_to_cache = symtab->GetWasSavedToCache();
|
|
|
|
|
if (module_stat.symtab_saved_to_cache)
|
|
|
|
|
++symtabs_saved;
|
|
|
|
|
}
|
2021-10-25 18:03:06 -07:00
|
|
|
SymbolFile *sym_file = module->GetSymbolFile();
|
|
|
|
|
if (sym_file) {
|
2024-02-06 19:47:34 -05:00
|
|
|
if (!summary_only) {
|
|
|
|
|
if (sym_file->GetObjectFile() != module->GetObjectFile())
|
|
|
|
|
module_stat.symfile_path =
|
|
|
|
|
sym_file->GetObjectFile()->GetFileSpec().GetPath();
|
|
|
|
|
ModuleList symbol_modules = sym_file->GetDebugInfoModules();
|
|
|
|
|
for (const auto &symbol_module : symbol_modules.Modules())
|
|
|
|
|
module_stat.symfile_modules.push_back((intptr_t)symbol_module.get());
|
|
|
|
|
}
|
2021-12-28 10:49:59 -08:00
|
|
|
module_stat.debug_info_index_loaded_from_cache =
|
|
|
|
|
sym_file->GetDebugInfoIndexWasLoadedFromCache();
|
|
|
|
|
if (module_stat.debug_info_index_loaded_from_cache)
|
|
|
|
|
++debug_index_loaded;
|
|
|
|
|
module_stat.debug_info_index_saved_to_cache =
|
|
|
|
|
sym_file->GetDebugInfoIndexWasSavedToCache();
|
|
|
|
|
if (module_stat.debug_info_index_saved_to_cache)
|
|
|
|
|
++debug_index_saved;
|
2024-02-06 19:47:34 -05:00
|
|
|
module_stat.debug_index_time = sym_file->GetDebugInfoIndexTime().count();
|
|
|
|
|
module_stat.debug_parse_time = sym_file->GetDebugInfoParseTime().count();
|
2024-02-19 00:33:23 -05:00
|
|
|
module_stat.debug_info_size =
|
|
|
|
|
sym_file->GetDebugInfoSize(load_all_debug_info);
|
2022-04-20 07:30:53 -07:00
|
|
|
module_stat.symtab_stripped = module->GetObjectFile()->IsStripped();
|
|
|
|
|
if (module_stat.symtab_stripped)
|
|
|
|
|
++num_stripped_modules;
|
|
|
|
|
module_stat.debug_info_enabled = sym_file->GetLoadDebugInfoEnabled() &&
|
|
|
|
|
module_stat.debug_info_size > 0;
|
2022-09-22 17:54:06 -07:00
|
|
|
module_stat.debug_info_had_variable_errors =
|
|
|
|
|
sym_file->GetDebugInfoHadFrameVariableErrors();
|
2022-04-20 07:30:53 -07:00
|
|
|
if (module_stat.debug_info_enabled)
|
|
|
|
|
++num_debug_info_enabled_modules;
|
|
|
|
|
if (module_stat.debug_info_size > 0)
|
|
|
|
|
++num_modules_has_debug_info;
|
2022-11-20 09:40:23 -08:00
|
|
|
if (module_stat.debug_info_had_variable_errors)
|
|
|
|
|
++num_modules_with_variable_errors;
|
2021-10-25 18:03:06 -07:00
|
|
|
}
|
2021-10-21 16:01:00 -07:00
|
|
|
symtab_parse_time += module_stat.symtab_parse_time;
|
|
|
|
|
symtab_index_time += module_stat.symtab_index_time;
|
2021-10-25 18:03:06 -07:00
|
|
|
debug_parse_time += module_stat.debug_parse_time;
|
|
|
|
|
debug_index_time += module_stat.debug_index_time;
|
|
|
|
|
debug_info_size += module_stat.debug_info_size;
|
2022-11-14 16:24:36 -08:00
|
|
|
module->ForEachTypeSystem([&](lldb::TypeSystemSP ts) {
|
2022-10-31 14:50:04 -07:00
|
|
|
if (auto stats = ts->ReportStatistics())
|
|
|
|
|
module_stat.type_system_stats.insert({ts->GetPluginName(), *stats});
|
2022-11-23 20:28:03 -08:00
|
|
|
if (ts->GetHasForcefullyCompletedTypes())
|
|
|
|
|
module_stat.debug_info_had_incomplete_types = true;
|
2022-10-31 14:50:04 -07:00
|
|
|
return true;
|
|
|
|
|
});
|
2022-11-23 20:28:03 -08:00
|
|
|
if (module_stat.debug_info_had_incomplete_types)
|
|
|
|
|
++num_modules_with_incomplete_types;
|
|
|
|
|
|
2024-02-06 19:47:34 -05:00
|
|
|
if (!summary_only) {
|
|
|
|
|
module_stat.identifier = (intptr_t)module;
|
|
|
|
|
module_stat.path = module->GetFileSpec().GetPath();
|
|
|
|
|
if (ConstString object_name = module->GetObjectName()) {
|
|
|
|
|
module_stat.path.append(1, '(');
|
|
|
|
|
module_stat.path.append(object_name.GetStringRef().str());
|
|
|
|
|
module_stat.path.append(1, ')');
|
|
|
|
|
}
|
|
|
|
|
module_stat.uuid = module->GetUUID().GetAsString();
|
|
|
|
|
module_stat.triple = module->GetArchitecture().GetTriple().str();
|
|
|
|
|
json_modules.emplace_back(module_stat.ToJSON());
|
|
|
|
|
}
|
2021-10-21 16:01:00 -07:00
|
|
|
}
|
|
|
|
|
|
2021-10-20 14:49:09 -07:00
|
|
|
json::Object global_stats{
|
2021-10-21 16:01:00 -07:00
|
|
|
{"totalSymbolTableParseTime", symtab_parse_time},
|
|
|
|
|
{"totalSymbolTableIndexTime", symtab_index_time},
|
2021-12-28 10:49:59 -08:00
|
|
|
{"totalSymbolTablesLoadedFromCache", symtabs_loaded},
|
|
|
|
|
{"totalSymbolTablesSavedToCache", symtabs_saved},
|
2021-10-25 18:03:06 -07:00
|
|
|
{"totalDebugInfoParseTime", debug_parse_time},
|
|
|
|
|
{"totalDebugInfoIndexTime", debug_index_time},
|
2021-12-28 10:49:59 -08:00
|
|
|
{"totalDebugInfoIndexLoadedFromCache", debug_index_loaded},
|
|
|
|
|
{"totalDebugInfoIndexSavedToCache", debug_index_saved},
|
2021-10-25 18:03:06 -07:00
|
|
|
{"totalDebugInfoByteSize", debug_info_size},
|
2022-04-20 07:30:53 -07:00
|
|
|
{"totalModuleCount", num_modules},
|
|
|
|
|
{"totalModuleCountHasDebugInfo", num_modules_has_debug_info},
|
2022-11-20 09:40:23 -08:00
|
|
|
{"totalModuleCountWithVariableErrors", num_modules_with_variable_errors},
|
2024-02-05 13:17:29 -08:00
|
|
|
{"totalModuleCountWithIncompleteTypes",
|
|
|
|
|
num_modules_with_incomplete_types},
|
2022-04-20 07:30:53 -07:00
|
|
|
{"totalDebugInfoEnabled", num_debug_info_enabled_modules},
|
|
|
|
|
{"totalSymbolTableStripped", num_stripped_modules},
|
2021-10-20 14:49:09 -07:00
|
|
|
};
|
2024-02-06 19:47:34 -05:00
|
|
|
|
|
|
|
|
if (target) {
|
|
|
|
|
json_targets.emplace_back(target->ReportStatistics(options));
|
|
|
|
|
} else {
|
|
|
|
|
for (const auto &target : debugger.GetTargetList().Targets())
|
|
|
|
|
json_targets.emplace_back(target->ReportStatistics(options));
|
|
|
|
|
}
|
|
|
|
|
global_stats.try_emplace("targets", std::move(json_targets));
|
|
|
|
|
|
|
|
|
|
if (!summary_only) {
|
|
|
|
|
ConstStringStats const_string_stats;
|
|
|
|
|
json::Object json_memory{
|
|
|
|
|
{"strings", const_string_stats.ToJSON()},
|
|
|
|
|
};
|
|
|
|
|
json::Value cmd_stats = debugger.GetCommandInterpreter().GetStatistics();
|
|
|
|
|
global_stats.try_emplace("modules", std::move(json_modules));
|
|
|
|
|
global_stats.try_emplace("memory", std::move(json_memory));
|
|
|
|
|
global_stats.try_emplace("commands", std::move(cmd_stats));
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-20 14:49:09 -07:00
|
|
|
return std::move(global_stats);
|
|
|
|
|
}
|