Author: Dave Lee Date: 2024-12-10T09:36:38-08:00 New Revision: 1a650fde4a885420c6f2991b41039c4b16ff42e1
URL: https://github.com/llvm/llvm-project/commit/1a650fde4a885420c6f2991b41039c4b16ff42e1 DIFF: https://github.com/llvm/llvm-project/commit/1a650fde4a885420c6f2991b41039c4b16ff42e1.diff LOG: [lldb] Load embedded type summary section (#7859) (#8040) Add support for type summaries embedded into the binary. These embedded summaries will typically be generated by Swift macros, but can also be generated by any other means. rdar://115184658 Added: lldb/test/API/functionalities/data-formatter/embedded-summary/Makefile lldb/test/API/functionalities/data-formatter/embedded-summary/TestEmbeddedTypeSummary.py lldb/test/API/functionalities/data-formatter/embedded-summary/main.c Modified: lldb/include/lldb/lldb-enumerations.h lldb/source/Core/Section.cpp lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp lldb/source/Symbol/ObjectFile.cpp lldb/source/Target/Target.cpp Removed: ################################################################################ diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index a9a66ea2662f39..e00ec7f17c5cb8 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -763,6 +763,7 @@ enum SectionType { eSectionTypeDWARFDebugLocListsDwo, eSectionTypeDWARFDebugTuIndex, eSectionTypeCTF, + eSectionTypeLLDBTypeSummaries, eSectionTypeSwiftModules, }; diff --git a/lldb/source/Core/Section.cpp b/lldb/source/Core/Section.cpp index 0763e88d4608f4..ee01b4ce06ca1e 100644 --- a/lldb/source/Core/Section.cpp +++ b/lldb/source/Core/Section.cpp @@ -147,6 +147,8 @@ const char *Section::GetTypeAsCString() const { return "dwarf-gnu-debugaltlink"; case eSectionTypeCTF: return "ctf"; + case eSectionTypeLLDBTypeSummaries: + return "lldb-type-summaries"; case eSectionTypeOther: return "regular"; case eSectionTypeSwiftModules: @@ -457,6 +459,7 @@ bool Section::ContainsOnlyDebugInfo() const { case eSectionTypeDWARFAppleObjC: case eSectionTypeDWARFGNUDebugAltLink: case eSectionTypeCTF: + case eSectionTypeLLDBTypeSummaries: case eSectionTypeSwiftModules: return true; } diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index eac9ab4577d3eb..a8249cf103833e 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -1696,6 +1696,7 @@ static SectionType GetSectionTypeFromName(llvm::StringRef Name) { .Case(".gnu_debugaltlink", eSectionTypeDWARFGNUDebugAltLink) .Case(".gosymtab", eSectionTypeGoSymtab) .Case(".text", eSectionTypeCode) + .Case(".lldbsummaries", lldb::eSectionTypeLLDBTypeSummaries) .Case(".swift_ast", eSectionTypeSwiftModules) .Default(eSectionTypeOther); } diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index daffa1379fe575..7e17fd8c53cd01 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -1209,6 +1209,7 @@ AddressClass ObjectFileMachO::GetAddressClass(lldb::addr_t file_addr) { case eSectionTypeDWARFAppleObjC: case eSectionTypeDWARFGNUDebugAltLink: case eSectionTypeCTF: + case eSectionTypeLLDBTypeSummaries: case eSectionTypeSwiftModules: return AddressClass::eDebug; @@ -1484,6 +1485,7 @@ static lldb::SectionType GetSectionType(uint32_t flags, static ConstString g_sect_name_data("__data"); static ConstString g_sect_name_go_symtab("__gosymtab"); static ConstString g_sect_name_ctf("__ctf"); + static ConstString g_sect_name_lldb_summaries("__lldbsummaries"); static ConstString g_sect_name_swift_ast("__swift_ast"); if (section_name == g_sect_name_dwarf_debug_abbrev) @@ -1564,6 +1566,8 @@ static lldb::SectionType GetSectionType(uint32_t flags, return eSectionTypeGoSymtab; if (section_name == g_sect_name_ctf) return eSectionTypeCTF; + if (section_name == g_sect_name_lldb_summaries) + return lldb::eSectionTypeLLDBTypeSummaries; if (section_name == g_sect_name_swift_ast) return eSectionTypeSwiftModules; if (section_name == g_sect_name_objc_data || diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp index 8d9c919bc9b101..bb712da7f6d67d 100644 --- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp +++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp @@ -1010,6 +1010,7 @@ SectionType ObjectFilePECOFF::GetSectionType(llvm::StringRef sect_name, // .eh_frame can be truncated to 8 chars. .Cases(".eh_frame", ".eh_fram", eSectionTypeEHFrame) .Case(".gosymtab", eSectionTypeGoSymtab) + .Case(".lldbsummaries", lldb::eSectionTypeLLDBTypeSummaries) .Case("swiftast", eSectionTypeSwiftModules) .Default(eSectionTypeInvalid); if (section_type != eSectionTypeInvalid) diff --git a/lldb/source/Symbol/ObjectFile.cpp b/lldb/source/Symbol/ObjectFile.cpp index 35317d209de1f9..3100e6b813b631 100644 --- a/lldb/source/Symbol/ObjectFile.cpp +++ b/lldb/source/Symbol/ObjectFile.cpp @@ -366,6 +366,7 @@ AddressClass ObjectFile::GetAddressClass(addr_t file_addr) { case eSectionTypeDWARFAppleObjC: case eSectionTypeDWARFGNUDebugAltLink: case eSectionTypeCTF: + case eSectionTypeLLDBTypeSummaries: case eSectionTypeSwiftModules: return AddressClass::eDebug; case eSectionTypeEHFrame: diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 4bac94f35d6cfb..9ac85ad3ed5ee6 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -24,6 +24,9 @@ #include "lldb/Core/Section.h" #include "lldb/Core/SourceManager.h" #include "lldb/Core/StructuredDataImpl.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/DataFormatters/DataVisualization.h" #include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/ExpressionVariable.h" #include "lldb/Expression/REPL.h" @@ -1538,6 +1541,76 @@ static void LoadScriptingResourceForModule(const ModuleSP &module_sp, feedback_stream.GetData()); } +// Load type summaries embedded in the binary. These are type summaries provided +// by the authors of the code. +static void LoadTypeSummariesForModule(ModuleSP module_sp) { + auto *sections = module_sp->GetSectionList(); + if (!sections) + return; + + auto summaries_sp = + sections->FindSectionByType(eSectionTypeLLDBTypeSummaries, true); + if (!summaries_sp) + return; + + Log *log = GetLog(LLDBLog::DataFormatters); + const char *module_name = module_sp->GetObjectName().GetCString(); + + TypeCategoryImplSP category; + DataVisualization::Categories::GetCategory(ConstString("default"), category); + + // The type summary record is serialized as follows. + // + // Each record contains, in order: + // * Version number of the record format + // * The remaining size of the record + // * The size of the type identifier + // * The type identifier, either a type name, or a regex + // * The size of the summary string + // * The summary string + // + // Integers are encoded using ULEB. + // + // Strings are encoded with first a length (ULEB), then the string contents, + // and lastly a null terminator. The length includes the null. + + DataExtractor extractor; + auto section_size = summaries_sp->GetSectionData(extractor); + lldb::offset_t offset = 0; + while (offset < section_size) { + uint64_t version = extractor.GetULEB128(&offset); + uint64_t record_size = extractor.GetULEB128(&offset); + if (version == 1) { + uint64_t type_size = extractor.GetULEB128(&offset); + llvm::StringRef type_name = extractor.GetCStr(&offset, type_size); + uint64_t summary_size = extractor.GetULEB128(&offset); + llvm::StringRef summary_string = extractor.GetCStr(&offset, summary_size); + if (!type_name.empty() && !summary_string.empty()) { + TypeSummaryImpl::Flags flags; + auto summary_sp = + std::make_shared<StringSummaryFormat>(flags, summary_string.data()); + FormatterMatchType match_type = eFormatterMatchExact; + if (summary_string.front() == '^' && summary_string.back() == '$') + match_type = eFormatterMatchRegex; + category->AddTypeSummary(type_name, match_type, summary_sp); + LLDB_LOGF(log, "Loaded embedded type summary for '%s' from %s.", + type_name.data(), module_name); + } else { + if (type_name.empty()) + LLDB_LOGF(log, "Missing string(s) in embedded type summary in %s.", + module_name); + } + } else { + // Skip unsupported record. + offset += record_size; + LLDB_LOGF( + log, + "Skipping unsupported embedded type summary of version %llu in %s.", + version, module_name); + } + } +} + void Target::ClearModules(bool delete_locations) { ModulesDidUnload(m_images, delete_locations); m_section_load_history.Clear(); @@ -1818,6 +1891,7 @@ void Target::ModulesDidLoad(ModuleList &module_list) { for (size_t idx = 0; idx < num_images; ++idx) { ModuleSP module_sp(module_list.GetModuleAtIndex(idx)); LoadScriptingResourceForModule(module_sp, this); + LoadTypeSummariesForModule(module_sp); } m_breakpoint_list.UpdateBreakpoints(module_list, true, false); m_internal_breakpoint_list.UpdateBreakpoints(module_list, true, false); diff --git a/lldb/test/API/functionalities/data-formatter/embedded-summary/Makefile b/lldb/test/API/functionalities/data-formatter/embedded-summary/Makefile new file mode 100644 index 00000000000000..c9319d6e6888a4 --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/embedded-summary/Makefile @@ -0,0 +1,2 @@ +C_SOURCES := main.c +include Makefile.rules diff --git a/lldb/test/API/functionalities/data-formatter/embedded-summary/TestEmbeddedTypeSummary.py b/lldb/test/API/functionalities/data-formatter/embedded-summary/TestEmbeddedTypeSummary.py new file mode 100644 index 00000000000000..b8ce7d9f76eb9e --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/embedded-summary/TestEmbeddedTypeSummary.py @@ -0,0 +1,12 @@ +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestCase(TestBase): + @skipUnlessDarwin + def test(self): + self.build() + lldbutil.run_to_source_breakpoint(self, "break here", lldb.SBFileSpec("main.c")) + self.expect("v player", substrs=['"Dirk" (41)']) diff --git a/lldb/test/API/functionalities/data-formatter/embedded-summary/main.c b/lldb/test/API/functionalities/data-formatter/embedded-summary/main.c new file mode 100644 index 00000000000000..9ddd64246f726c --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/embedded-summary/main.c @@ -0,0 +1,22 @@ +#include <stdio.h> + +struct Player { + char *name; + int number; +}; + +__attribute__((used, section("__DATA_CONST,__lldbsummaries"))) unsigned char + _Player_type_summary[] = "\x01" // version + "\x25" // record size + "\x07" // type name size + "Player\0" // type name + "\x1c" // summary string size + "${var.name} (${var.number})"; // summary string + +int main() { + struct Player player; + player.name = "Dirk"; + player.number = 41; + puts("break here"); + return 0; +} _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits