Skip to content

[lldb] Load embedded type summary section (#7859) #8040

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lldb/include/lldb/lldb-enumerations.h
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,7 @@ enum SectionType {
eSectionTypeDWARFDebugLocListsDwo,
eSectionTypeDWARFDebugTuIndex,
eSectionTypeCTF,
eSectionTypeLLDBTypeSummaries,
eSectionTypeSwiftModules,
};

Expand Down
3 changes: 3 additions & 0 deletions lldb/source/Core/Section.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,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:
Expand Down Expand Up @@ -459,6 +461,7 @@ bool Section::ContainsOnlyDebugInfo() const {
case eSectionTypeDWARFAppleObjC:
case eSectionTypeDWARFGNUDebugAltLink:
case eSectionTypeCTF:
case eSectionTypeLLDBTypeSummaries:
#ifdef LLDB_ENABLE_SWIFT
case eSectionTypeSwiftModules:
#endif
Expand Down
1 change: 1 addition & 0 deletions lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1693,6 +1693,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);
}
Expand Down
4 changes: 4 additions & 0 deletions lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1205,6 +1205,7 @@ AddressClass ObjectFileMachO::GetAddressClass(lldb::addr_t file_addr) {
case eSectionTypeDWARFAppleObjC:
case eSectionTypeDWARFGNUDebugAltLink:
case eSectionTypeCTF:
case eSectionTypeLLDBTypeSummaries:
case eSectionTypeSwiftModules:
return AddressClass::eDebug;

Expand Down Expand Up @@ -1482,6 +1483,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)
Expand Down Expand Up @@ -1562,6 +1564,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 ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1012,6 +1012,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)
Expand Down
1 change: 1 addition & 0 deletions lldb/source/Symbol/ObjectFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ AddressClass ObjectFile::GetAddressClass(addr_t file_addr) {
case eSectionTypeDWARFAppleObjC:
case eSectionTypeDWARFGNUDebugAltLink:
case eSectionTypeCTF:
case eSectionTypeLLDBTypeSummaries:
case eSectionTypeSwiftModules:
return AddressClass::eDebug;
case eSectionTypeEHFrame:
Expand Down
72 changes: 72 additions & 0 deletions lldb/source/Target/Target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#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"
Expand Down Expand Up @@ -1477,6 +1478,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();
Expand Down Expand Up @@ -1721,6 +1792,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);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
C_SOURCES := main.c
include Makefile.rules
Original file line number Diff line number Diff line change
@@ -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)'])
Original file line number Diff line number Diff line change
@@ -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;
}