void Clear() { m_sections.clear(); }
+ /// Get the debug information size from all sections that contain debug
+ /// information. Symbol tables are not considered part of the debug
+ /// information for this call, just known sections that contain debug
+ /// information.
+ uint64_t GetDebugInfoSize() const;
+
protected:
collection m_sections;
};
void SetIsRelocated(bool b) { m_relocated = b; }
+ /// Returns true if this section contains debug information. Symbol tables
+ /// are not considered debug information since some symbols might contain
+ /// debug information (STABS, COFF) but not all symbols do, so to keep this
+ /// fast and simple only sections that contains only debug information should
+ /// return true.
+ bool ContainsOnlyDebugInfo() const;
+
protected:
ObjectFile *m_obj_file; // The object file that data for this section should
// be read from
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/TypeList.h"
#include "lldb/Symbol/TypeSystem.h"
+#include "lldb/Target/Statistics.h"
#include "lldb/Utility/XcodeSDK.h"
#include "lldb/lldb-private.h"
#include "llvm/ADT/DenseSet.h"
virtual void Dump(Stream &s);
+ /// Metrics gathering functions
+
+ /// Return the size in bytes of all debug information in the symbol file.
+ ///
+ /// If the debug information is contained in sections of an ObjectFile, then
+ /// this call should add the size of all sections that contain debug
+ /// information. Symbols the symbol tables are not considered debug
+ /// information for this call to make it easy and quick for this number to be
+ /// calculated. If the symbol file is all debug information, the size of the
+ /// entire file should be returned. The default implementation of this
+ /// function will iterate over all sections in a module and add up their
+ /// debug info only section byte sizes.
+ virtual uint64_t GetDebugInfoSize();
+
+ /// Return the time taken to parse the debug information.
+ ///
+ /// \returns 0.0 if no information has been parsed or if there is
+ /// no computational cost to parsing the debug information.
+ virtual StatsDuration GetDebugInfoParseTime() {
+ return StatsDuration(0.0);
+ }
+
+ /// Return the time it took to index the debug information in the object
+ /// file.
+ ///
+ /// \returns 0.0 if the file doesn't need to be indexed or if it
+ /// hasn't been indexed yet, or a valid duration if it has.
+ virtual StatsDuration GetDebugInfoIndexTime() {
+ return StatsDuration(0.0);
+ }
+
+
protected:
void AssertModuleLock();
virtual uint32_t CalculateNumCompileUnits() = 0;
std::string triple;
double symtab_parse_time = 0.0;
double symtab_index_time = 0.0;
+ double debug_parse_time = 0.0;
+ double debug_index_time = 0.0;
+ uint64_t debug_info_size = 0;
};
/// A class that represents statistics for a since lldb_private::Target.
return 0;
}
+bool Section::ContainsOnlyDebugInfo() const {
+ switch (m_type) {
+ case eSectionTypeInvalid:
+ case eSectionTypeCode:
+ case eSectionTypeContainer:
+ case eSectionTypeData:
+ case eSectionTypeDataCString:
+ case eSectionTypeDataCStringPointers:
+ case eSectionTypeDataSymbolAddress:
+ case eSectionTypeData4:
+ case eSectionTypeData8:
+ case eSectionTypeData16:
+ case eSectionTypeDataPointers:
+ case eSectionTypeZeroFill:
+ case eSectionTypeDataObjCMessageRefs:
+ case eSectionTypeDataObjCCFStrings:
+ case eSectionTypeELFSymbolTable:
+ case eSectionTypeELFDynamicSymbols:
+ case eSectionTypeELFRelocationEntries:
+ case eSectionTypeELFDynamicLinkInfo:
+ case eSectionTypeEHFrame:
+ case eSectionTypeARMexidx:
+ case eSectionTypeARMextab:
+ case eSectionTypeCompactUnwind:
+ case eSectionTypeGoSymtab:
+ case eSectionTypeAbsoluteAddress:
+ case eSectionTypeOther:
+ return false;
+
+ case eSectionTypeDebug:
+ case eSectionTypeDWARFDebugAbbrev:
+ case eSectionTypeDWARFDebugAbbrevDwo:
+ case eSectionTypeDWARFDebugAddr:
+ case eSectionTypeDWARFDebugAranges:
+ case eSectionTypeDWARFDebugCuIndex:
+ case eSectionTypeDWARFDebugTuIndex:
+ case eSectionTypeDWARFDebugFrame:
+ case eSectionTypeDWARFDebugInfo:
+ case eSectionTypeDWARFDebugInfoDwo:
+ case eSectionTypeDWARFDebugLine:
+ case eSectionTypeDWARFDebugLineStr:
+ case eSectionTypeDWARFDebugLoc:
+ case eSectionTypeDWARFDebugLocDwo:
+ case eSectionTypeDWARFDebugLocLists:
+ case eSectionTypeDWARFDebugLocListsDwo:
+ case eSectionTypeDWARFDebugMacInfo:
+ case eSectionTypeDWARFDebugMacro:
+ case eSectionTypeDWARFDebugPubNames:
+ case eSectionTypeDWARFDebugPubTypes:
+ case eSectionTypeDWARFDebugRanges:
+ case eSectionTypeDWARFDebugRngLists:
+ case eSectionTypeDWARFDebugRngListsDwo:
+ case eSectionTypeDWARFDebugStr:
+ case eSectionTypeDWARFDebugStrDwo:
+ case eSectionTypeDWARFDebugStrOffsets:
+ case eSectionTypeDWARFDebugStrOffsetsDwo:
+ case eSectionTypeDWARFDebugTypes:
+ case eSectionTypeDWARFDebugTypesDwo:
+ case eSectionTypeDWARFDebugNames:
+ case eSectionTypeDWARFAppleNames:
+ case eSectionTypeDWARFAppleTypes:
+ case eSectionTypeDWARFAppleNamespaces:
+ case eSectionTypeDWARFAppleObjC:
+ case eSectionTypeDWARFGNUDebugAltLink:
+ return true;
+ }
+ return false;
+}
+
+
#pragma mark SectionList
SectionList &SectionList::operator=(const SectionList &rhs) {
}
return count;
}
+
+uint64_t SectionList::GetDebugInfoSize() const {
+ uint64_t debug_info_size = 0;
+ for (const auto §ion : m_sections) {
+ const SectionList &sub_sections = section->GetChildren();
+ if (sub_sections.GetSize() > 0)
+ debug_info_size += sub_sections.GetDebugInfoSize();
+ else if (section->ContainsOnlyDebugInfo())
+ debug_info_size += section->GetFileSize();
+ }
+ return debug_info_size;
+}
}
m_unwind_data->win.Sort();
}
+
+uint64_t SymbolFileBreakpad::GetDebugInfoSize() {
+ // Breakpad files are all debug info.
+ return m_objfile_sp->GetByteSize();
+}
+
return GetPluginNameStatic().GetStringRef();
}
+ uint64_t GetDebugInfoSize() override;
+
private:
// A class representing a position in the breakpad file. Useful for
// remembering the position so we can go back to it later and parse more data.
#include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
#include "Plugins/SymbolFile/DWARF/DWARFFormValue.h"
+#include "lldb/Target/Statistics.h"
+
class DWARFDeclContext;
class DWARFDIE;
virtual void Dump(Stream &s) = 0;
+ StatsDuration GetIndexTime() { return m_index_time; }
+
protected:
Module &m_module;
+ StatsDuration m_index_time{0.0};
/// Helper function implementing common logic for processing function dies. If
/// the function given by "ref" matches search criteria given by
if (m_first_die)
return; // Already parsed
+ ElapsedTime elapsed(m_dwarf.GetDebugInfoParseTimeRef());
LLDB_SCOPED_TIMERF("%8.8x: DWARFUnit::ExtractUnitDIENoDwoIfNeeded()",
GetOffset());
void DWARFUnit::ExtractDIEsRWLocked() {
llvm::sys::ScopedWriter first_die_lock(m_first_die_mutex);
+ ElapsedTime elapsed(m_dwarf.GetDebugInfoParseTimeRef());
LLDB_SCOPED_TIMERF("%8.8x: DWARFUnit::ExtractDIEsIfNeeded()", GetOffset());
// Set the offset to that of the first DIE and calculate the start of the
SymbolFileDWARF &main_dwarf = *m_dwarf;
m_dwarf = nullptr;
+ ElapsedTime elapsed(m_index_time);
LLDB_SCOPED_TIMERF("%p", static_cast<void *>(&main_dwarf));
DWARFDebugInfo &main_info = main_dwarf.DebugInfo();
if (offset == DW_INVALID_OFFSET)
return false;
+ ElapsedTime elapsed(m_parse_time);
llvm::DWARFDebugLine::Prologue prologue;
if (!ParseLLVMLineTablePrologue(m_context, prologue, offset,
dwarf_cu.GetOffset()))
"SymbolFileDWARF::GetTypeUnitSupportFiles failed to parse "
"the line table prologue");
};
+ ElapsedTime elapsed(m_parse_time);
llvm::Error error = prologue.parse(data, &line_table_offset, report, ctx);
if (error) {
report(std::move(error));
if (offset == DW_INVALID_OFFSET)
return false;
+ ElapsedTime elapsed(m_parse_time);
llvm::DWARFDebugLine line;
const llvm::DWARFDebugLine::LineTable *line_table =
ParseLLVMLineTable(m_context, line, offset, dwarf_cu->GetOffset());
if (iter != m_debug_macros_map.end())
return iter->second;
+ ElapsedTime elapsed(m_parse_time);
const DWARFDataExtractor &debug_macro_data = m_context.getOrLoadMacroData();
if (debug_macro_data.GetByteSize() == 0)
return DebugMacrosSP();
lang = DW_LANG_C_plus_plus;
return LanguageTypeFromDWARF(lang);
}
+
+StatsDuration SymbolFileDWARF::GetDebugInfoIndexTime() {
+ if (m_index)
+ return m_index->GetIndexTime();
+ return StatsDuration(0.0);
+}
#include "lldb/Symbol/DebugMacros.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Target/Statistics.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Flags.h"
#include "lldb/Utility/RangeMap.h"
/// Same as GetLanguage() but reports all C++ versions as C++ (no version).
static lldb::LanguageType GetLanguageFamily(DWARFUnit &unit);
+ lldb_private::StatsDuration GetDebugInfoParseTime() override {
+ return m_parse_time;
+ }
+ lldb_private::StatsDuration GetDebugInfoIndexTime() override;
+
+ lldb_private::StatsDuration &GetDebugInfoParseTimeRef() {
+ return m_parse_time;
+ }
+
+
protected:
typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *>
DIEToTypePtr;
/// Try to filter out this debug info by comparing it to the lowest code
/// address in the module.
lldb::addr_t m_first_code_address = LLDB_INVALID_ADDRESS;
+ lldb_private::StatsDuration m_parse_time{0.0};
};
#endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_SYMBOLFILEDWARF_H
}
return num_line_entries_added;
}
+
+uint64_t SymbolFileDWARFDebugMap::GetDebugInfoSize() {
+ uint64_t debug_info_size = 0;
+ ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
+ ObjectFile *oso_objfile = oso_dwarf->GetObjectFile();
+ if (!oso_objfile)
+ return false; // Keep iterating
+ ModuleSP module_sp = oso_objfile->GetModule();
+ if (!module_sp)
+ return false; // Keep iterating
+ SectionList *section_list = module_sp->GetSectionList();
+ if (section_list)
+ debug_info_size += section_list->GetDebugInfoSize();
+ return false; // Keep iterating
+ });
+ return debug_info_size;
+}
+
+StatsDuration SymbolFileDWARFDebugMap::GetDebugInfoParseTime() {
+ StatsDuration elapsed(0.0);
+ ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
+ ObjectFile *oso_objfile = oso_dwarf->GetObjectFile();
+ if (oso_objfile) {
+ ModuleSP module_sp = oso_objfile->GetModule();
+ if (module_sp) {
+ SymbolFile *symfile = module_sp->GetSymbolFile();
+ if (symfile)
+ elapsed += symfile->GetDebugInfoParseTime();
+ }
+ }
+ return false; // Keep iterating
+ });
+ return elapsed;
+}
+
+StatsDuration SymbolFileDWARFDebugMap::GetDebugInfoIndexTime() {
+ StatsDuration elapsed(0.0);
+ ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
+ ObjectFile *oso_objfile = oso_dwarf->GetObjectFile();
+ if (oso_objfile) {
+ ModuleSP module_sp = oso_objfile->GetModule();
+ if (module_sp) {
+ SymbolFile *symfile = module_sp->GetSymbolFile();
+ if (symfile)
+ elapsed += symfile->GetDebugInfoIndexTime();
+ }
+ }
+ return false; // Keep iterating
+ });
+ return elapsed;
+}
return GetPluginNameStatic().GetStringRef();
}
+ uint64_t GetDebugInfoSize() override;
+ lldb_private::StatsDuration GetDebugInfoParseTime() override;
+ lldb_private::StatsDuration GetDebugInfoIndexTime() override;
+
protected:
enum { kHaveInitializedOSOs = (1 << 0), kNumFlags };
}
return type_system_or_err;
}
+
+uint64_t SymbolFileNativePDB::GetDebugInfoSize() {
+ // PDB files are a separate file that contains all debug info.
+ return m_index->pdb().getFileSize();
+}
+
void InitializeObject() override;
+ uint64_t GetDebugInfoSize() override;
+
// Compile Unit function calls
void
}
SymbolFile::RegisterInfoResolver::~RegisterInfoResolver() = default;
+
+uint64_t SymbolFile::GetDebugInfoSize() {
+ if (!m_objfile_sp)
+ return 0;
+ ModuleSP module_sp(m_objfile_sp->GetModule());
+ if (!module_sp)
+ return 0;
+ const SectionList *section_list = module_sp->GetSectionList();
+ if (section_list)
+ return section_list->GetDebugInfoSize();
+ return 0;
+}
module.try_emplace("identifier", identifier);
module.try_emplace("symbolTableParseTime", symtab_parse_time);
module.try_emplace("symbolTableIndexTime", symtab_index_time);
+ module.try_emplace("debugInfoParseTime", debug_parse_time);
+ module.try_emplace("debugInfoIndexTime", debug_index_time);
+ module.try_emplace("debugInfoByteSize", (int64_t)debug_info_size);
return module;
}
json::Array json_modules;
double symtab_parse_time = 0.0;
double symtab_index_time = 0.0;
+ double debug_parse_time = 0.0;
+ double debug_index_time = 0.0;
+ uint64_t debug_info_size = 0;
if (target) {
json_targets.emplace_back(target->ReportStatistics());
} else {
std::lock_guard<std::recursive_mutex> guard(
Module::GetAllocationModuleCollectionMutex());
const size_t num_modules = Module::GetNumberAllocatedModules();
- ModuleSP module_sp;
for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
Module *module = Module::GetAllocatedModuleAtIndex(image_idx);
ModuleStats module_stat;
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();
module_stat.symtab_parse_time = module->GetSymtabParseTime().count();
module_stat.symtab_index_time = module->GetSymtabIndexTime().count();
+ SymbolFile *sym_file = module->GetSymbolFile();
+ if (sym_file) {
+ module_stat.debug_index_time = sym_file->GetDebugInfoIndexTime().count();
+ module_stat.debug_parse_time = sym_file->GetDebugInfoParseTime().count();
+ module_stat.debug_info_size = sym_file->GetDebugInfoSize();
+ }
symtab_parse_time += module_stat.symtab_parse_time;
symtab_index_time += module_stat.symtab_index_time;
+ debug_parse_time += module_stat.debug_parse_time;
+ debug_index_time += module_stat.debug_index_time;
+ debug_info_size += module_stat.debug_info_size;
json_modules.emplace_back(module_stat.ToJSON());
}
{"modules", std::move(json_modules)},
{"totalSymbolTableParseTime", symtab_parse_time},
{"totalSymbolTableIndexTime", symtab_index_time},
+ {"totalDebugInfoParseTime", debug_parse_time},
+ {"totalDebugInfoIndexTime", debug_index_time},
+ {"totalDebugInfoByteSize", debug_info_size},
};
return std::move(global_stats);
}
"moduleIdentifiers": [...],
}
],
+ "totalDebugInfoByteSize": 182522234,
+ "totalDebugInfoIndexTime": 2.33343,
+ "totalDebugInfoParseTime": 8.2121400240000071,
"totalSymbolTableParseTime": 0.123,
"totalSymbolTableIndexTime": 0.234,
}
'targets',
'totalSymbolTableParseTime',
'totalSymbolTableIndexTime',
+ 'totalDebugInfoByteSize',
+ 'totalDebugInfoIndexTime',
+ 'totalDebugInfoParseTime',
]
self.verify_keys(debug_stats, '"debug_stats"', debug_stat_keys, None)
stats = debug_stats['targets'][0]
},
}
],
+ "totalDebugInfoByteSize": 182522234,
+ "totalDebugInfoIndexTime": 2.33343,
+ "totalDebugInfoParseTime": 8.2121400240000071,
"totalSymbolTableParseTime": 0.123,
"totalSymbolTableIndexTime": 0.234,
}
'targets',
'totalSymbolTableParseTime',
'totalSymbolTableIndexTime',
+ 'totalDebugInfoByteSize',
+ 'totalDebugInfoIndexTime',
+ 'totalDebugInfoParseTime',
]
self.verify_keys(debug_stats, '"debug_stats"', debug_stat_keys, None)
stats = debug_stats['targets'][0]
'targets',
'totalSymbolTableParseTime',
'totalSymbolTableIndexTime',
+ 'totalDebugInfoParseTime',
+ 'totalDebugInfoIndexTime',
+ 'totalDebugInfoByteSize'
]
self.verify_keys(debug_stats, '"debug_stats"', debug_stat_keys, None)
stats = debug_stats['targets'][0]
self.verify_keys(stats, '"stats"', keys_exist, None)
exe_module = self.find_module_in_metrics(exe, debug_stats)
module_keys = [
+ 'debugInfoByteSize',
+ 'debugInfoIndexTime',
+ 'debugInfoParseTime',
'identifier',
'path',
'symbolTableIndexTime',