https://github.com/zw3917 updated https://github.com/llvm/llvm-project/pull/155023
>From d978cb5b17b7a8450226825a8fd85f2054166059 Mon Sep 17 00:00:00 2001 From: Ziyi Wang <zw3...@nyu.edu> Date: Fri, 22 Aug 2025 09:17:25 -0700 Subject: [PATCH 1/6] [lldb] Add count for errors of DWO files in statistics --- lldb/include/lldb/Symbol/SymbolFile.h | 4 + lldb/include/lldb/Target/Statistics.h | 1 + .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 18 +++ .../SymbolFile/DWARF/SymbolFileDWARF.h | 3 + lldb/source/Target/Statistics.cpp | 5 + .../commands/statistics/basic/TestStats.py | 115 ++++++++++++++++++ .../statistics/basic/dwo_error_foo.cpp | 10 ++ .../statistics/basic/dwo_error_main.cpp | 5 + 8 files changed, 161 insertions(+) create mode 100644 lldb/test/API/commands/statistics/basic/dwo_error_foo.cpp create mode 100644 lldb/test/API/commands/statistics/basic/dwo_error_main.cpp diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h index bbc615d9fdc38..7f590fc2e7e64 100644 --- a/lldb/include/lldb/Symbol/SymbolFile.h +++ b/lldb/include/lldb/Symbol/SymbolFile.h @@ -496,6 +496,10 @@ class SymbolFile : public PluginInterface { /// symbol file doesn't support DWO files, both counts will be 0. virtual std::pair<uint32_t, uint32_t> GetDwoFileCounts() { return {0, 0}; } + /// Calculates the count of dwo load error, return the number of dwo file with + /// errors, 0 by default. + virtual uint32_t CountDwoLoadErrors() { return 0; } + virtual lldb::TypeSP MakeType(lldb::user_id_t uid, ConstString name, std::optional<uint64_t> byte_size, SymbolContextScope *context, diff --git a/lldb/include/lldb/Target/Statistics.h b/lldb/include/lldb/Target/Statistics.h index 55dff8861a9ab..6dd09cac890b8 100644 --- a/lldb/include/lldb/Target/Statistics.h +++ b/lldb/include/lldb/Target/Statistics.h @@ -155,6 +155,7 @@ struct ModuleStats { bool debug_info_had_incomplete_types = false; uint32_t dwo_file_count = 0; uint32_t loaded_dwo_file_count = 0; + uint32_t dwo_load_error_count = 0; }; struct ConstStringStats { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 9958af26379b9..51ad43894d982 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -4529,3 +4529,21 @@ std::pair<uint32_t, uint32_t> SymbolFileDWARF::GetDwoFileCounts() { return {loaded_dwo_count, total_dwo_count}; } + +uint32_t SymbolFileDWARF::CountDwoLoadErrors() { + uint32_t dwo_load_error_count = 0; + + DWARFDebugInfo &info = DebugInfo(); + const size_t num_cus = info.GetNumUnits(); + for (size_t cu_idx = 0; cu_idx < num_cus; cu_idx++) { + DWARFUnit *dwarf_cu = info.GetUnitAtIndex(cu_idx); + if (dwarf_cu == nullptr) + continue; + + // Check if this unit has dwo error (False by default). + const Status &dwo_error = dwarf_cu->GetDwoError(); + if (dwo_error.Fail()) + dwo_load_error_count++; + } + return dwo_load_error_count; +} diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index d7db8a3c0869f..349ea9ef8224b 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -288,6 +288,9 @@ class SymbolFileDWARF : public SymbolFileCommon { // CUs and total DWO CUs. For non-split-dwarf files, this reports 0 for both. std::pair<uint32_t, uint32_t> GetDwoFileCounts() override; + /// Count the number of dwo load errors happened. + uint32_t CountDwoLoadErrors() override; + DWARFContext &GetDWARFContext() { return m_context; } const std::shared_ptr<SymbolFileDWARFDwo> &GetDwpSymbolFile(); diff --git a/lldb/source/Target/Statistics.cpp b/lldb/source/Target/Statistics.cpp index 909f335687b21..20ade32f488ea 100644 --- a/lldb/source/Target/Statistics.cpp +++ b/lldb/source/Target/Statistics.cpp @@ -75,6 +75,7 @@ json::Value ModuleStats::ToJSON() const { module.try_emplace("symbolTableSymbolCount", symtab_symbol_count); module.try_emplace("dwoFileCount", dwo_file_count); module.try_emplace("loadedDwoFileCount", loaded_dwo_file_count); + module.try_emplace("dwoLoadErrorCount", dwo_load_error_count); if (!symbol_locator_time.map.empty()) { json::Object obj; @@ -326,6 +327,7 @@ llvm::json::Value DebuggerStats::ReportStatistics( uint32_t symtab_symbol_count = 0; uint32_t total_loaded_dwo_file_count = 0; uint32_t total_dwo_file_count = 0; + uint32_t total_dwo_load_error_count = 0; for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { Module *module = target != nullptr ? target->GetImages().GetModuleAtIndex(image_idx).get() @@ -361,6 +363,8 @@ llvm::json::Value DebuggerStats::ReportStatistics( sym_file->GetDwoFileCounts(); total_dwo_file_count += module_stat.dwo_file_count; total_loaded_dwo_file_count += module_stat.loaded_dwo_file_count; + module_stat.dwo_load_error_count += current_dwo_errors; + total_dwo_load_error_count += current_dwo_errors; module_stat.debug_info_index_loaded_from_cache = sym_file->GetDebugInfoIndexWasLoadedFromCache(); if (module_stat.debug_info_index_loaded_from_cache) @@ -437,6 +441,7 @@ llvm::json::Value DebuggerStats::ReportStatistics( {"totalSymbolTableSymbolCount", symtab_symbol_count}, {"totalLoadedDwoFileCount", total_loaded_dwo_file_count}, {"totalDwoFileCount", total_dwo_file_count}, + {"totalDwoLoadErrorCount", total_dwo_load_error_count}, }; if (include_targets) { diff --git a/lldb/test/API/commands/statistics/basic/TestStats.py b/lldb/test/API/commands/statistics/basic/TestStats.py index e9ee8b8661e5a..7a2dc213ce6fd 100644 --- a/lldb/test/API/commands/statistics/basic/TestStats.py +++ b/lldb/test/API/commands/statistics/basic/TestStats.py @@ -1,6 +1,8 @@ +import glob import json import os import re +import shutil import lldb from lldbsuite.test.decorators import * @@ -179,6 +181,7 @@ def test_default_no_run(self): "totalDebugInfoParseTime", "totalDwoFileCount", "totalLoadedDwoFileCount", + "totalDwoLoadErrorCount", ] self.verify_keys(debug_stats, '"debug_stats"', debug_stat_keys, None) if self.getPlatform() != "windows": @@ -291,6 +294,7 @@ def test_default_with_run(self): "totalDebugInfoParseTime", "totalDwoFileCount", "totalLoadedDwoFileCount", + "totalDwoLoadErrorCount", ] self.verify_keys(debug_stats, '"debug_stats"', debug_stat_keys, None) stats = debug_stats["targets"][0] @@ -331,6 +335,7 @@ def test_memory(self): "totalDebugInfoByteSize", "totalDwoFileCount", "totalLoadedDwoFileCount", + "totalDwoLoadErrorCount", ] self.verify_keys(debug_stats, '"debug_stats"', debug_stat_keys, None) @@ -385,6 +390,7 @@ def test_modules(self): "totalDebugInfoByteSize", "totalDwoFileCount", "totalLoadedDwoFileCount", + "totalDwoLoadErrorCount", ] self.verify_keys(debug_stats, '"debug_stats"', debug_stat_keys, None) stats = debug_stats["targets"][0] @@ -407,6 +413,7 @@ def test_modules(self): "symbolTableSavedToCache", "dwoFileCount", "loadedDwoFileCount", + "dwoLoadErrorCount", "triple", "uuid", ] @@ -497,6 +504,7 @@ def test_breakpoints(self): "totalDebugInfoByteSize", "totalDwoFileCount", "totalLoadedDwoFileCount", + "totalDwoLoadErrorCount", ] self.verify_keys(debug_stats, '"debug_stats"', debug_stat_keys, None) target_stats = debug_stats["targets"][0] @@ -655,6 +663,113 @@ def test_dwp_dwo_file_count(self): self.assertEqual(debug_stats["totalDwoFileCount"], 2) self.assertEqual(debug_stats["totalLoadedDwoFileCount"], 2) + @add_test_categories(["dwo"]) + def test_dwo_missing_error_stats(self): + """ + Test that DWO missing errors are reported correctly in statistics. + This test: + 1) Builds a program with split DWARF (.dwo files) + 2) Delete all two .dwo files + 3) Verify that 2 DWO load errors are reported in statistics + """ + da = { + "CXX_SOURCES": "dwo_error_main.cpp dwo_error_foo.cpp", + "EXE": self.getBuildArtifact("a.out"), + } + # -gsplit-dwarf creates separate .dwo files, + # Expected output: dwo_error_main.dwo (contains main) and dwo_error_foo.dwo (contains foo struct/function) + self.build(dictionary=da, debug_info="dwo") + self.addTearDownCleanup(dictionary=da) + exe = self.getBuildArtifact("a.out") + + # Remove the two .dwo files to trigger a DWO load error + dwo_files = glob.glob(self.getBuildArtifact("*.dwo")) + for dwo_file in dwo_files: + os.rename(dwo_file, dwo_file + ".bak") + + target = self.createTestTarget(file_path=exe) + debug_stats = self.get_stats() + + # Check DWO load error statistics are reported + self.assertIn("totalDwoLoadErrorCount", debug_stats) + self.assertEqual(debug_stats["totalDwoLoadErrorCount"], 2) + + # Since there's only one module, module stats should have the same count as total count + self.assertIn("dwoLoadErrorCount", debug_stats["modules"][0]) + self.assertEqual(debug_stats["modules"][0]["dwoLoadErrorCount"], 2) + + # Restore the original .dwo file + for dwo_file in dwo_files: + os.rename(dwo_file + ".bak", dwo_file) + + @add_test_categories(["dwo"]) + def test_dwo_id_mismatch_error_stats(self): + """ + Test that DWO ID mismatch errors are reported correctly in statistics. + This test: + 1) Builds a program with split DWARF (.dwo files) + 2) Change one of the source file content and rebuild + 3) Replace the new .dwo file with the original one to create a DWO ID mismatch + 4) Verifies that a DWO load error is reported in statistics + 5) Restores the original source file + """ + da = { + "CXX_SOURCES": "dwo_error_main.cpp dwo_error_foo.cpp", + "EXE": self.getBuildArtifact("a.out"), + } + # -gsplit-dwarf creates separate .dwo files, + # Expected output: dwo_error_main.dwo (contains main) and dwo_error_foo.dwo (contains foo struct/function) + self.build(dictionary=da, debug_info="dwo") + self.addTearDownCleanup(dictionary=da) + exe = self.getBuildArtifact("a.out") + + # Find and make a backup of the original .dwo file + dwo_files = glob.glob(self.getBuildArtifact("*.dwo")) + + original_dwo_file = dwo_files[1] + original_dwo_backup = original_dwo_file + ".bak" + shutil.copy2(original_dwo_file, original_dwo_backup) + + target = self.createTestTarget(file_path=exe) + initial_stats = self.get_stats() + self.assertIn("totalDwoLoadErrorCount", initial_stats) + self.assertEqual(initial_stats["totalDwoLoadErrorCount"], 0) + self.dbg.DeleteTarget(target) + + # Get the original file size before modification + source_file_path = self.getSourcePath("dwo_error_foo.cpp") + original_size = os.path.getsize(source_file_path) + + try: + # Modify the source code and rebuild + with open(source_file_path, "a") as f: + f.write("\n void additional_foo(){}\n") + + # Rebuild and replace the new .dwo file with the original one + self.build(dictionary=da, debug_info="dwo") + shutil.copy2(original_dwo_backup, original_dwo_file) + + # Create a new target and run to a breakpoint to force DWO file loading + target = self.createTestTarget(file_path=exe) + debug_stats = self.get_stats() + + # Check that DWO load error statistics are reported + self.assertIn("totalDwoLoadErrorCount", debug_stats) + self.assertEqual(debug_stats["totalDwoLoadErrorCount"], 1) + + # Since there's only one module, module stats should have the same count as total count + self.assertIn("dwoLoadErrorCount", debug_stats["modules"][0]) + self.assertEqual(debug_stats["modules"][0]["dwoLoadErrorCount"], 1) + + finally: + # Remove the appended content + with open(source_file_path, "a") as f: + f.truncate(original_size) + + # Restore the original .dwo file + if os.path.exists(original_dwo_backup): + os.unlink(original_dwo_backup) + @skipUnlessDarwin @no_debug_info_test def test_dsym_binary_has_symfile_in_stats(self): diff --git a/lldb/test/API/commands/statistics/basic/dwo_error_foo.cpp b/lldb/test/API/commands/statistics/basic/dwo_error_foo.cpp new file mode 100644 index 0000000000000..41618bdcee958 --- /dev/null +++ b/lldb/test/API/commands/statistics/basic/dwo_error_foo.cpp @@ -0,0 +1,10 @@ +struct foo { + int x; + bool y; +}; + +void dwo_error_foo() { + foo f; + f.x = 1; + f.y = true; +} diff --git a/lldb/test/API/commands/statistics/basic/dwo_error_main.cpp b/lldb/test/API/commands/statistics/basic/dwo_error_main.cpp new file mode 100644 index 0000000000000..4f09bd74e1fd6 --- /dev/null +++ b/lldb/test/API/commands/statistics/basic/dwo_error_main.cpp @@ -0,0 +1,5 @@ +void dwo_error_foo(); +int main() { + dwo_error_foo(); + return 0; +} >From 698bc9ea4b70ecb3981380615579a296ac064999 Mon Sep 17 00:00:00 2001 From: Ziyi Wang <zw3...@nyu.edu> Date: Sun, 24 Aug 2025 16:24:54 -0700 Subject: [PATCH 2/6] Combine DWO counting statistics into a single DWOStats struct --- lldb/include/lldb/Symbol/SymbolFile.h | 24 +++++++----- lldb/include/lldb/Target/Statistics.h | 2 +- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 37 ++++++------------- .../SymbolFile/DWARF/SymbolFileDWARF.h | 12 +++--- lldb/source/Target/Statistics.cpp | 21 ++++++----- .../commands/statistics/basic/TestStats.py | 24 ++++++------ 6 files changed, 56 insertions(+), 64 deletions(-) diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h index 7f590fc2e7e64..49e3573292595 100644 --- a/lldb/include/lldb/Symbol/SymbolFile.h +++ b/lldb/include/lldb/Symbol/SymbolFile.h @@ -488,17 +488,23 @@ class SymbolFile : public PluginInterface { return false; }; - /// Get number of loaded/parsed DWO files. This is emitted in "statistics - /// dump" + /// Holds statistics about DWO (Debug With Object) files. + struct DWOStats { + uint32_t loaded_dwo_file_count = 0; + uint32_t dwo_file_count = 0; + uint32_t dwo_error_count = 0; + }; + + /// Retrieves statistics about DWO files associated with this symbol file. + /// This function returns a DWOStats struct containing: + /// - The number of successfully loaded/parsed DWO files. + /// - The total number of DWO files encountered. + /// - The number of DWO CUs that failed to load due to errors. + /// If this symbol file does not support DWO files, all counts will be zero. /// /// \returns - /// A pair containing (loaded_dwo_count, total_dwo_count). If this - /// symbol file doesn't support DWO files, both counts will be 0. - virtual std::pair<uint32_t, uint32_t> GetDwoFileCounts() { return {0, 0}; } - - /// Calculates the count of dwo load error, return the number of dwo file with - /// errors, 0 by default. - virtual uint32_t CountDwoLoadErrors() { return 0; } + /// A DWOStats struct with loaded, total, and error counts for DWO files. + virtual DWOStats GetDwoStats() { return {}; } virtual lldb::TypeSP MakeType(lldb::user_id_t uid, ConstString name, diff --git a/lldb/include/lldb/Target/Statistics.h b/lldb/include/lldb/Target/Statistics.h index 6dd09cac890b8..1cd78b195a7c9 100644 --- a/lldb/include/lldb/Target/Statistics.h +++ b/lldb/include/lldb/Target/Statistics.h @@ -155,7 +155,7 @@ struct ModuleStats { bool debug_info_had_incomplete_types = false; uint32_t dwo_file_count = 0; uint32_t loaded_dwo_file_count = 0; - uint32_t dwo_load_error_count = 0; + uint32_t dwo_error_count = 0; }; struct ConstStringStats { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 5c95200abd1bd..e41dfdf190697 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -90,7 +90,7 @@ #include <cctype> #include <cstring> -//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN +// #define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN #ifdef ENABLE_DEBUG_PRINTF #include <cstdio> @@ -1716,7 +1716,7 @@ SymbolFileDWARF *SymbolFileDWARF::GetDIERefSymbolFile(const DIERef &die_ref) { return this; if (file_index) { - // We have a SymbolFileDWARFDebugMap, so let it find the right file + // We have a SymbolFileDWARFDebugMap, so let it find the right file if (SymbolFileDWARFDebugMap *debug_map = GetDebugMapSymfile()) return debug_map->GetSymbolFileByOSOIndex(*file_index); @@ -1725,7 +1725,8 @@ SymbolFileDWARF *SymbolFileDWARF::GetDIERefSymbolFile(const DIERef &die_ref) { return GetDwpSymbolFile().get(); // DWP case // Handle the .dwo file case correctly - return DebugInfo().GetUnitAtIndex(*die_ref.file_index()) + return DebugInfo() + .GetUnitAtIndex(*die_ref.file_index()) ->GetDwoSymbolFile(); // DWO case } return this; @@ -4502,9 +4503,8 @@ void SymbolFileDWARF::GetCompileOptions( } } -std::pair<uint32_t, uint32_t> SymbolFileDWARF::GetDwoFileCounts() { - uint32_t total_dwo_count = 0; - uint32_t loaded_dwo_count = 0; +SymbolFile::DWOStats SymbolFileDWARF::GetDwoStats() { + SymbolFile::DWOStats stats; DWARFDebugInfo &info = DebugInfo(); const size_t num_cus = info.GetNumUnits(); @@ -4517,34 +4517,21 @@ std::pair<uint32_t, uint32_t> SymbolFileDWARF::GetDwoFileCounts() { if (!dwarf_cu->GetDWOId().has_value()) continue; - total_dwo_count++; + stats.dwo_file_count++; // If we have a DWO symbol file, that means we were able to successfully // load it. SymbolFile *dwo_symfile = dwarf_cu->GetDwoSymbolFile(/*load_all_debug_info=*/false); if (dwo_symfile) { - loaded_dwo_count++; + stats.loaded_dwo_file_count++; } - } - - return {loaded_dwo_count, total_dwo_count}; -} - -uint32_t SymbolFileDWARF::CountDwoLoadErrors() { - uint32_t dwo_load_error_count = 0; - - DWARFDebugInfo &info = DebugInfo(); - const size_t num_cus = info.GetNumUnits(); - for (size_t cu_idx = 0; cu_idx < num_cus; cu_idx++) { - DWARFUnit *dwarf_cu = info.GetUnitAtIndex(cu_idx); - if (dwarf_cu == nullptr) - continue; - // Check if this unit has dwo error (False by default). + // Check if this unit has a DWO load error, false by default. const Status &dwo_error = dwarf_cu->GetDwoError(); if (dwo_error.Fail()) - dwo_load_error_count++; + stats.dwo_error_count++; } - return dwo_load_error_count; + + return stats; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 349ea9ef8224b..8b8cb5859e8a0 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -283,13 +283,11 @@ class SymbolFileDWARF : public SymbolFileCommon { bool GetSeparateDebugInfo(StructuredData::Dictionary &d, bool errors_only, bool load_all_debug_info = false) override; - // Gets a pair of loaded and total dwo file counts. - // For split-dwarf files, this reports the counts for successfully loaded DWO - // CUs and total DWO CUs. For non-split-dwarf files, this reports 0 for both. - std::pair<uint32_t, uint32_t> GetDwoFileCounts() override; - - /// Count the number of dwo load errors happened. - uint32_t CountDwoLoadErrors() override; + /// Gets statistics about dwo files associated with this symbol file. + /// For split-dwarf files, this reports the counts for successfully loaded DWO + /// CUs, total DWO CUs, and the number of DWO CUs with loading errors. + /// For non-split-dwarf files, this reports 0 for all. + DWOStats GetDwoStats() override; DWARFContext &GetDWARFContext() { return m_context; } diff --git a/lldb/source/Target/Statistics.cpp b/lldb/source/Target/Statistics.cpp index 0f9eb5a785163..0dab6aa0b7861 100644 --- a/lldb/source/Target/Statistics.cpp +++ b/lldb/source/Target/Statistics.cpp @@ -75,7 +75,7 @@ json::Value ModuleStats::ToJSON() const { module.try_emplace("symbolTableSymbolCount", symtab_symbol_count); module.try_emplace("dwoFileCount", dwo_file_count); module.try_emplace("loadedDwoFileCount", loaded_dwo_file_count); - module.try_emplace("dwoLoadErrorCount", dwo_load_error_count); + module.try_emplace("dwoErrorCount", dwo_error_count); if (!symbol_locator_time.map.empty()) { json::Object obj; @@ -327,7 +327,7 @@ llvm::json::Value DebuggerStats::ReportStatistics( uint32_t symtab_symbol_count = 0; uint32_t total_loaded_dwo_file_count = 0; uint32_t total_dwo_file_count = 0; - uint32_t total_dwo_load_error_count = 0; + uint32_t total_dwo_error_count = 0; for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { Module *module = target != nullptr ? target->GetImages().GetModuleAtIndex(image_idx).get() @@ -359,13 +359,14 @@ llvm::json::Value DebuggerStats::ReportStatistics( for (const auto &symbol_module : symbol_modules.Modules()) module_stat.symfile_modules.push_back((intptr_t)symbol_module.get()); } - std::tie(module_stat.loaded_dwo_file_count, module_stat.dwo_file_count) = - sym_file->GetDwoFileCounts(); - total_dwo_file_count += module_stat.dwo_file_count; - total_loaded_dwo_file_count += module_stat.loaded_dwo_file_count; - uint32_t current_dwo_errors = sym_file->CountDwoLoadErrors(); - module_stat.dwo_load_error_count += current_dwo_errors; - total_dwo_load_error_count += current_dwo_errors; + SymbolFile::DWOStats current_dwo_stats = sym_file->GetDwoStats(); + module_stat.loaded_dwo_file_count += + current_dwo_stats.loaded_dwo_file_count; + module_stat.dwo_file_count += current_dwo_stats.dwo_file_count; + module_stat.dwo_error_count += current_dwo_stats.dwo_error_count; + total_dwo_file_count += current_dwo_stats.dwo_file_count; + total_loaded_dwo_file_count += current_dwo_stats.loaded_dwo_file_count; + total_dwo_error_count += current_dwo_stats.dwo_error_count; module_stat.debug_info_index_loaded_from_cache = sym_file->GetDebugInfoIndexWasLoadedFromCache(); if (module_stat.debug_info_index_loaded_from_cache) @@ -442,7 +443,7 @@ llvm::json::Value DebuggerStats::ReportStatistics( {"totalSymbolTableSymbolCount", symtab_symbol_count}, {"totalLoadedDwoFileCount", total_loaded_dwo_file_count}, {"totalDwoFileCount", total_dwo_file_count}, - {"totalDwoLoadErrorCount", total_dwo_load_error_count}, + {"totalDwoErrorCount", total_dwo_error_count}, }; if (include_targets) { diff --git a/lldb/test/API/commands/statistics/basic/TestStats.py b/lldb/test/API/commands/statistics/basic/TestStats.py index 7a2dc213ce6fd..d41877eaf8996 100644 --- a/lldb/test/API/commands/statistics/basic/TestStats.py +++ b/lldb/test/API/commands/statistics/basic/TestStats.py @@ -670,7 +670,7 @@ def test_dwo_missing_error_stats(self): This test: 1) Builds a program with split DWARF (.dwo files) 2) Delete all two .dwo files - 3) Verify that 2 DWO load errors are reported in statistics + 3) Verify that 2 DWO errors are reported in statistics """ da = { "CXX_SOURCES": "dwo_error_main.cpp dwo_error_foo.cpp", @@ -691,12 +691,12 @@ def test_dwo_missing_error_stats(self): debug_stats = self.get_stats() # Check DWO load error statistics are reported - self.assertIn("totalDwoLoadErrorCount", debug_stats) - self.assertEqual(debug_stats["totalDwoLoadErrorCount"], 2) + self.assertIn("totalDwoErrorCount", debug_stats) + self.assertEqual(debug_stats["totalDwoErrorCount"], 2) # Since there's only one module, module stats should have the same count as total count - self.assertIn("dwoLoadErrorCount", debug_stats["modules"][0]) - self.assertEqual(debug_stats["modules"][0]["dwoLoadErrorCount"], 2) + self.assertIn("dwoErrorCount", debug_stats["modules"][0]) + self.assertEqual(debug_stats["modules"][0]["dwoErrorCount"], 2) # Restore the original .dwo file for dwo_file in dwo_files: @@ -710,7 +710,7 @@ def test_dwo_id_mismatch_error_stats(self): 1) Builds a program with split DWARF (.dwo files) 2) Change one of the source file content and rebuild 3) Replace the new .dwo file with the original one to create a DWO ID mismatch - 4) Verifies that a DWO load error is reported in statistics + 4) Verifies that a DWO error is reported in statistics 5) Restores the original source file """ da = { @@ -732,8 +732,8 @@ def test_dwo_id_mismatch_error_stats(self): target = self.createTestTarget(file_path=exe) initial_stats = self.get_stats() - self.assertIn("totalDwoLoadErrorCount", initial_stats) - self.assertEqual(initial_stats["totalDwoLoadErrorCount"], 0) + self.assertIn("totalDwoErrorCount", initial_stats) + self.assertEqual(initial_stats["totalDwoErrorCount"], 0) self.dbg.DeleteTarget(target) # Get the original file size before modification @@ -754,12 +754,12 @@ def test_dwo_id_mismatch_error_stats(self): debug_stats = self.get_stats() # Check that DWO load error statistics are reported - self.assertIn("totalDwoLoadErrorCount", debug_stats) - self.assertEqual(debug_stats["totalDwoLoadErrorCount"], 1) + self.assertIn("totalDwoErrorCount", debug_stats) + self.assertEqual(debug_stats["totalDwoErrorCount"], 1) # Since there's only one module, module stats should have the same count as total count - self.assertIn("dwoLoadErrorCount", debug_stats["modules"][0]) - self.assertEqual(debug_stats["modules"][0]["dwoLoadErrorCount"], 1) + self.assertIn("dwoErrorCount", debug_stats["modules"][0]) + self.assertEqual(debug_stats["modules"][0]["dwoErrorCount"], 1) finally: # Remove the appended content >From 3881633f1bb7a1af20d15d26f4539dd5b0ab1c90 Mon Sep 17 00:00:00 2001 From: Ziyi Wang <zw3...@nyu.edu> Date: Thu, 28 Aug 2025 13:29:23 -0700 Subject: [PATCH 3/6] Reuse DWOStats in Statistics --- lldb/include/lldb/Symbol/SymbolFile.h | 46 +++++++++++++++------------ lldb/include/lldb/Target/Statistics.h | 5 ++- lldb/source/Target/Statistics.cpp | 25 ++++++--------- 3 files changed, 37 insertions(+), 39 deletions(-) diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h index 49e3573292595..671a2483783bf 100644 --- a/lldb/include/lldb/Symbol/SymbolFile.h +++ b/lldb/include/lldb/Symbol/SymbolFile.h @@ -493,6 +493,12 @@ class SymbolFile : public PluginInterface { uint32_t loaded_dwo_file_count = 0; uint32_t dwo_file_count = 0; uint32_t dwo_error_count = 0; + + DWOStats operator+(const DWOStats &rhs) const { + return DWOStats{loaded_dwo_file_count + rhs.loaded_dwo_file_count, + dwo_file_count + rhs.dwo_file_count, + dwo_error_count + rhs.dwo_error_count}; + } }; /// Retrieves statistics about DWO files associated with this symbol file. @@ -506,14 +512,15 @@ class SymbolFile : public PluginInterface { /// A DWOStats struct with loaded, total, and error counts for DWO files. virtual DWOStats GetDwoStats() { return {}; } - virtual lldb::TypeSP - MakeType(lldb::user_id_t uid, ConstString name, - std::optional<uint64_t> byte_size, SymbolContextScope *context, - lldb::user_id_t encoding_uid, - Type::EncodingDataType encoding_uid_type, const Declaration &decl, - const CompilerType &compiler_qual_type, - Type::ResolveState compiler_type_resolve_state, - uint32_t opaque_payload = 0) = 0; + virtual lldb::TypeSP MakeType(lldb::user_id_t uid, ConstString name, + std::optional<uint64_t> byte_size, + SymbolContextScope *context, + lldb::user_id_t encoding_uid, + Type::EncodingDataType encoding_uid_type, + const Declaration &decl, + const CompilerType &compiler_qual_type, + Type::ResolveState compiler_type_resolve_state, + uint32_t opaque_payload = 0) = 0; virtual lldb::TypeSP CopyType(const lldb::TypeSP &other_type) = 0; @@ -607,7 +614,7 @@ class SymbolFileCommon : public SymbolFile { return m_debug_info_had_variable_errors; } void SetDebugInfoHadFrameVariableErrors() override { - m_debug_info_had_variable_errors = true; + m_debug_info_had_variable_errors = true; } /// This function is used to create types that belong to a SymbolFile. The @@ -622,21 +629,20 @@ class SymbolFileCommon : public SymbolFile { const CompilerType &compiler_qual_type, Type::ResolveState compiler_type_resolve_state, uint32_t opaque_payload = 0) override { - lldb::TypeSP type_sp (new Type( - uid, this, name, byte_size, context, encoding_uid, - encoding_uid_type, decl, compiler_qual_type, - compiler_type_resolve_state, opaque_payload)); - m_type_list.Insert(type_sp); - return type_sp; + lldb::TypeSP type_sp(new Type( + uid, this, name, byte_size, context, encoding_uid, encoding_uid_type, + decl, compiler_qual_type, compiler_type_resolve_state, opaque_payload)); + m_type_list.Insert(type_sp); + return type_sp; } lldb::TypeSP CopyType(const lldb::TypeSP &other_type) override { - // Make sure the real symbol file matches when copying types. - if (GetBackingSymbolFile() != other_type->GetSymbolFile()) + // Make sure the real symbol file matches when copying types. + if (GetBackingSymbolFile() != other_type->GetSymbolFile()) return lldb::TypeSP(); - lldb::TypeSP type_sp(new Type(*other_type)); - m_type_list.Insert(type_sp); - return type_sp; + lldb::TypeSP type_sp(new Type(*other_type)); + m_type_list.Insert(type_sp); + return type_sp; } protected: diff --git a/lldb/include/lldb/Target/Statistics.h b/lldb/include/lldb/Target/Statistics.h index 1cd78b195a7c9..bf00dd3eb146d 100644 --- a/lldb/include/lldb/Target/Statistics.h +++ b/lldb/include/lldb/Target/Statistics.h @@ -10,6 +10,7 @@ #define LLDB_TARGET_STATISTICS_H #include "lldb/DataFormatters/TypeSummary.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/RealpathPrefixes.h" #include "lldb/Utility/Stream.h" @@ -153,9 +154,7 @@ struct ModuleStats { bool symtab_stripped = false; bool debug_info_had_variable_errors = false; bool debug_info_had_incomplete_types = false; - uint32_t dwo_file_count = 0; - uint32_t loaded_dwo_file_count = 0; - uint32_t dwo_error_count = 0; + SymbolFile::DWOStats dwo_stats; }; struct ConstStringStats { diff --git a/lldb/source/Target/Statistics.cpp b/lldb/source/Target/Statistics.cpp index 0dab6aa0b7861..b0e2257705b5e 100644 --- a/lldb/source/Target/Statistics.cpp +++ b/lldb/source/Target/Statistics.cpp @@ -73,9 +73,9 @@ json::Value ModuleStats::ToJSON() const { debug_info_had_incomplete_types); module.try_emplace("symbolTableStripped", symtab_stripped); module.try_emplace("symbolTableSymbolCount", symtab_symbol_count); - module.try_emplace("dwoFileCount", dwo_file_count); - module.try_emplace("loadedDwoFileCount", loaded_dwo_file_count); - module.try_emplace("dwoErrorCount", dwo_error_count); + module.try_emplace("dwoFileCount", dwo_stats.dwo_file_count); + module.try_emplace("loadedDwoFileCount", dwo_stats.loaded_dwo_file_count); + module.try_emplace("dwoErrorCount", dwo_stats.dwo_error_count); if (!symbol_locator_time.map.empty()) { json::Object obj; @@ -325,9 +325,7 @@ llvm::json::Value DebuggerStats::ReportStatistics( uint32_t num_modules_with_incomplete_types = 0; uint32_t num_stripped_modules = 0; uint32_t symtab_symbol_count = 0; - uint32_t total_loaded_dwo_file_count = 0; - uint32_t total_dwo_file_count = 0; - uint32_t total_dwo_error_count = 0; + SymbolFile::DWOStats total_dwo_stats; for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { Module *module = target != nullptr ? target->GetImages().GetModuleAtIndex(image_idx).get() @@ -360,13 +358,8 @@ llvm::json::Value DebuggerStats::ReportStatistics( module_stat.symfile_modules.push_back((intptr_t)symbol_module.get()); } SymbolFile::DWOStats current_dwo_stats = sym_file->GetDwoStats(); - module_stat.loaded_dwo_file_count += - current_dwo_stats.loaded_dwo_file_count; - module_stat.dwo_file_count += current_dwo_stats.dwo_file_count; - module_stat.dwo_error_count += current_dwo_stats.dwo_error_count; - total_dwo_file_count += current_dwo_stats.dwo_file_count; - total_loaded_dwo_file_count += current_dwo_stats.loaded_dwo_file_count; - total_dwo_error_count += current_dwo_stats.dwo_error_count; + module_stat.dwo_stats += current_dwo_stats; + total_dwo_stats += current_dwo_stats; module_stat.debug_info_index_loaded_from_cache = sym_file->GetDebugInfoIndexWasLoadedFromCache(); if (module_stat.debug_info_index_loaded_from_cache) @@ -441,9 +434,9 @@ llvm::json::Value DebuggerStats::ReportStatistics( {"totalDebugInfoEnabled", num_debug_info_enabled_modules}, {"totalSymbolTableStripped", num_stripped_modules}, {"totalSymbolTableSymbolCount", symtab_symbol_count}, - {"totalLoadedDwoFileCount", total_loaded_dwo_file_count}, - {"totalDwoFileCount", total_dwo_file_count}, - {"totalDwoErrorCount", total_dwo_error_count}, + {"totalLoadedDwoFileCount", total_dwo_stats.loaded_dwo_file_count}, + {"totalDwoFileCount", total_dwo_stats.dwo_file_count}, + {"totalDwoErrorCount", total_dwo_stats.dwo_error_count}, }; if (include_targets) { >From ec5dabd0a75ab86264b31dc40d049ac776dc6906 Mon Sep 17 00:00:00 2001 From: Ziyi Wang <zw3...@nyu.edu> Date: Thu, 28 Aug 2025 16:35:19 -0700 Subject: [PATCH 4/6] [lldb]Reuse DWOStats in statistics --- lldb/include/lldb/Symbol/SymbolFile.h | 13 ------------- lldb/include/lldb/Target/Statistics.h | 15 ++++++++++++++- .../Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 4 ++-- lldb/source/Target/Statistics.cpp | 8 ++++---- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h index 671a2483783bf..68c6563e7f314 100644 --- a/lldb/include/lldb/Symbol/SymbolFile.h +++ b/lldb/include/lldb/Symbol/SymbolFile.h @@ -488,19 +488,6 @@ class SymbolFile : public PluginInterface { return false; }; - /// Holds statistics about DWO (Debug With Object) files. - struct DWOStats { - uint32_t loaded_dwo_file_count = 0; - uint32_t dwo_file_count = 0; - uint32_t dwo_error_count = 0; - - DWOStats operator+(const DWOStats &rhs) const { - return DWOStats{loaded_dwo_file_count + rhs.loaded_dwo_file_count, - dwo_file_count + rhs.dwo_file_count, - dwo_error_count + rhs.dwo_error_count}; - } - }; - /// Retrieves statistics about DWO files associated with this symbol file. /// This function returns a DWOStats struct containing: /// - The number of successfully loaded/parsed DWO files. diff --git a/lldb/include/lldb/Target/Statistics.h b/lldb/include/lldb/Target/Statistics.h index bf00dd3eb146d..fac825229ec36 100644 --- a/lldb/include/lldb/Target/Statistics.h +++ b/lldb/include/lldb/Target/Statistics.h @@ -124,6 +124,19 @@ struct StatsSuccessFail { uint32_t failures = 0; }; +/// Holds statistics about DWO (Debug With Object) files. +struct DWOStats { + uint32_t loaded_dwo_file_count = 0; + uint32_t dwo_file_count = 0; + uint32_t dwo_error_count = 0; + + DWOStats operator+(const DWOStats &rhs) const { + return DWOStats{loaded_dwo_file_count + rhs.loaded_dwo_file_count, + dwo_file_count + rhs.dwo_file_count, + dwo_error_count + rhs.dwo_error_count}; + } +}; + /// A class that represents statistics for a since lldb_private::Module. struct ModuleStats { llvm::json::Value ToJSON() const; @@ -154,7 +167,7 @@ struct ModuleStats { bool symtab_stripped = false; bool debug_info_had_variable_errors = false; bool debug_info_had_incomplete_types = false; - SymbolFile::DWOStats dwo_stats; + DWOStats dwo_stats; }; struct ConstStringStats { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index e41dfdf190697..6f395b5a98afe 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -4503,8 +4503,8 @@ void SymbolFileDWARF::GetCompileOptions( } } -SymbolFile::DWOStats SymbolFileDWARF::GetDwoStats() { - SymbolFile::DWOStats stats; +DWOStats SymbolFileDWARF::GetDwoStats() { + DWOStats stats; DWARFDebugInfo &info = DebugInfo(); const size_t num_cus = info.GetNumUnits(); diff --git a/lldb/source/Target/Statistics.cpp b/lldb/source/Target/Statistics.cpp index b0e2257705b5e..3c16df5440f25 100644 --- a/lldb/source/Target/Statistics.cpp +++ b/lldb/source/Target/Statistics.cpp @@ -325,7 +325,7 @@ llvm::json::Value DebuggerStats::ReportStatistics( uint32_t num_modules_with_incomplete_types = 0; uint32_t num_stripped_modules = 0; uint32_t symtab_symbol_count = 0; - SymbolFile::DWOStats total_dwo_stats; + DWOStats total_dwo_stats; for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { Module *module = target != nullptr ? target->GetImages().GetModuleAtIndex(image_idx).get() @@ -357,9 +357,9 @@ llvm::json::Value DebuggerStats::ReportStatistics( for (const auto &symbol_module : symbol_modules.Modules()) module_stat.symfile_modules.push_back((intptr_t)symbol_module.get()); } - SymbolFile::DWOStats current_dwo_stats = sym_file->GetDwoStats(); - module_stat.dwo_stats += current_dwo_stats; - total_dwo_stats += current_dwo_stats; + DWOStats current_dwo_stats = sym_file->GetDwoStats(); + module_stat.dwo_stats = module_stat.dwo_stats + current_dwo_stats; + total_dwo_stats = total_dwo_stats + current_dwo_stats; module_stat.debug_info_index_loaded_from_cache = sym_file->GetDebugInfoIndexWasLoadedFromCache(); if (module_stat.debug_info_index_loaded_from_cache) >From 76850ec9c1805bc52393fbe8fc6810dd9ae3afd8 Mon Sep 17 00:00:00 2001 From: Ziyi Wang <zw3...@nyu.edu> Date: Thu, 28 Aug 2025 16:35:19 -0700 Subject: [PATCH 5/6] [lldb]Reuse DWOStats in statistics --- lldb/include/lldb/Target/Statistics.h | 1 - 1 file changed, 1 deletion(-) diff --git a/lldb/include/lldb/Target/Statistics.h b/lldb/include/lldb/Target/Statistics.h index fac825229ec36..c288917edbc6a 100644 --- a/lldb/include/lldb/Target/Statistics.h +++ b/lldb/include/lldb/Target/Statistics.h @@ -10,7 +10,6 @@ #define LLDB_TARGET_STATISTICS_H #include "lldb/DataFormatters/TypeSummary.h" -#include "lldb/Symbol/SymbolFile.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/RealpathPrefixes.h" #include "lldb/Utility/Stream.h" >From 3f866ad99a4163ef64a01c0566b8f246139c4749 Mon Sep 17 00:00:00 2001 From: Ziyi Wang <zw3...@nyu.edu> Date: Mon, 1 Sep 2025 23:03:13 -0700 Subject: [PATCH 6/6] [format]Revert for auto-formatter --- lldb/include/lldb/Symbol/SymbolFile.h | 40 +++++++++---------- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 7 ++-- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h index 68c6563e7f314..ad35b1defb5c9 100644 --- a/lldb/include/lldb/Symbol/SymbolFile.h +++ b/lldb/include/lldb/Symbol/SymbolFile.h @@ -499,15 +499,14 @@ class SymbolFile : public PluginInterface { /// A DWOStats struct with loaded, total, and error counts for DWO files. virtual DWOStats GetDwoStats() { return {}; } - virtual lldb::TypeSP MakeType(lldb::user_id_t uid, ConstString name, - std::optional<uint64_t> byte_size, - SymbolContextScope *context, - lldb::user_id_t encoding_uid, - Type::EncodingDataType encoding_uid_type, - const Declaration &decl, - const CompilerType &compiler_qual_type, - Type::ResolveState compiler_type_resolve_state, - uint32_t opaque_payload = 0) = 0; + virtual lldb::TypeSP + MakeType(lldb::user_id_t uid, ConstString name, + std::optional<uint64_t> byte_size, SymbolContextScope *context, + lldb::user_id_t encoding_uid, + Type::EncodingDataType encoding_uid_type, const Declaration &decl, + const CompilerType &compiler_qual_type, + Type::ResolveState compiler_type_resolve_state, + uint32_t opaque_payload = 0) = 0; virtual lldb::TypeSP CopyType(const lldb::TypeSP &other_type) = 0; @@ -601,7 +600,7 @@ class SymbolFileCommon : public SymbolFile { return m_debug_info_had_variable_errors; } void SetDebugInfoHadFrameVariableErrors() override { - m_debug_info_had_variable_errors = true; + m_debug_info_had_variable_errors = true; } /// This function is used to create types that belong to a SymbolFile. The @@ -616,20 +615,21 @@ class SymbolFileCommon : public SymbolFile { const CompilerType &compiler_qual_type, Type::ResolveState compiler_type_resolve_state, uint32_t opaque_payload = 0) override { - lldb::TypeSP type_sp(new Type( - uid, this, name, byte_size, context, encoding_uid, encoding_uid_type, - decl, compiler_qual_type, compiler_type_resolve_state, opaque_payload)); - m_type_list.Insert(type_sp); - return type_sp; + lldb::TypeSP type_sp (new Type( + uid, this, name, byte_size, context, encoding_uid, + encoding_uid_type, decl, compiler_qual_type, + compiler_type_resolve_state, opaque_payload)); + m_type_list.Insert(type_sp); + return type_sp; } lldb::TypeSP CopyType(const lldb::TypeSP &other_type) override { - // Make sure the real symbol file matches when copying types. - if (GetBackingSymbolFile() != other_type->GetSymbolFile()) + // Make sure the real symbol file matches when copying types. + if (GetBackingSymbolFile() != other_type->GetSymbolFile()) return lldb::TypeSP(); - lldb::TypeSP type_sp(new Type(*other_type)); - m_type_list.Insert(type_sp); - return type_sp; + lldb::TypeSP type_sp(new Type(*other_type)); + m_type_list.Insert(type_sp); + return type_sp; } protected: diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 6f395b5a98afe..7108ac72eb030 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -90,7 +90,7 @@ #include <cctype> #include <cstring> -// #define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN +//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN #ifdef ENABLE_DEBUG_PRINTF #include <cstdio> @@ -1716,7 +1716,7 @@ SymbolFileDWARF *SymbolFileDWARF::GetDIERefSymbolFile(const DIERef &die_ref) { return this; if (file_index) { - // We have a SymbolFileDWARFDebugMap, so let it find the right file + // We have a SymbolFileDWARFDebugMap, so let it find the right file if (SymbolFileDWARFDebugMap *debug_map = GetDebugMapSymfile()) return debug_map->GetSymbolFileByOSOIndex(*file_index); @@ -1725,8 +1725,7 @@ SymbolFileDWARF *SymbolFileDWARF::GetDIERefSymbolFile(const DIERef &die_ref) { return GetDwpSymbolFile().get(); // DWP case // Handle the .dwo file case correctly - return DebugInfo() - .GetUnitAtIndex(*die_ref.file_index()) + return DebugInfo().GetUnitAtIndex(*die_ref.file_index()) ->GetDwoSymbolFile(); // DWO case } return this; _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits