Skip to content

Commit a614c4d

Browse files
authored
[lldb] Load embedded type summary section (#7859)
Add support for type summaries embedded into the binary. These embedded summaries will typically be generated by macros, but can be generated by any other means. rdar://115184658
1 parent d947848 commit a614c4d

File tree

10 files changed

+120
-1
lines changed

10 files changed

+120
-1
lines changed

lldb/include/lldb/lldb-enumerations.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -770,6 +770,7 @@ enum SectionType {
770770
eSectionTypeDWARFDebugLocListsDwo,
771771
eSectionTypeDWARFDebugTuIndex,
772772
eSectionTypeCTF,
773+
eSectionTypeLLDBTypeSummaries,
773774
};
774775

775776
FLAGS_ENUM(EmulateInstructionOptions){

lldb/source/Core/Section.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,8 @@ const char *Section::GetTypeAsCString() const {
149149
return "dwarf-gnu-debugaltlink";
150150
case eSectionTypeCTF:
151151
return "ctf";
152+
case eSectionTypeLLDBTypeSummaries:
153+
return "lldb-type-summaries";
152154
case eSectionTypeOther:
153155
return "regular";
154156

@@ -465,6 +467,7 @@ bool Section::ContainsOnlyDebugInfo() const {
465467
case eSectionTypeDWARFAppleObjC:
466468
case eSectionTypeDWARFGNUDebugAltLink:
467469
case eSectionTypeCTF:
470+
case eSectionTypeLLDBTypeSummaries:
468471
return true;
469472
}
470473
return false;

lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1685,7 +1685,7 @@ static SectionType GetSectionTypeFromName(llvm::StringRef Name) {
16851685
.Case(".text", eSectionTypeCode)
16861686
// Swift support:
16871687
.Case(".swift_ast", eSectionTypeSwiftModules)
1688-
//
1688+
.Case(".lldbsummaries", lldb::eSectionTypeLLDBTypeSummaries)
16891689
.Default(eSectionTypeOther);
16901690
}
16911691

lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,6 +1208,7 @@ AddressClass ObjectFileMachO::GetAddressClass(lldb::addr_t file_addr) {
12081208
case eSectionTypeSwiftModules:
12091209
case eSectionTypeDWARFGNUDebugAltLink:
12101210
case eSectionTypeCTF:
1211+
case eSectionTypeLLDBTypeSummaries:
12111212
return AddressClass::eDebug;
12121213

12131214
case eSectionTypeEHFrame:
@@ -1485,6 +1486,7 @@ static lldb::SectionType GetSectionType(uint32_t flags,
14851486
static ConstString g_sect_name_swift_ast("__swift_ast");
14861487
static ConstString g_sect_name_go_symtab("__gosymtab");
14871488
static ConstString g_sect_name_ctf("__ctf");
1489+
static ConstString g_sect_name_lldb_summaries("__lldbsummaries");
14881490

14891491
if (section_name == g_sect_name_dwarf_debug_abbrev)
14901492
return eSectionTypeDWARFDebugAbbrev;
@@ -1573,6 +1575,9 @@ static lldb::SectionType GetSectionType(uint32_t flags,
15731575
section_name == g_sect_name_objc_classlist) {
15741576
return eSectionTypeDataPointers;
15751577
}
1578+
if (section_name == g_sect_name_lldb_summaries) {
1579+
return lldb::eSectionTypeLLDBTypeSummaries;
1580+
}
15761581

15771582
switch (mach_sect_type) {
15781583
// TODO: categorize sections by other flags for regular sections

lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,6 +1015,7 @@ SectionType ObjectFilePECOFF::GetSectionType(llvm::StringRef sect_name,
10151015
.Cases(".eh_frame", ".eh_fram", eSectionTypeEHFrame)
10161016
.Case(".gosymtab", eSectionTypeGoSymtab)
10171017
.Case("swiftast", eSectionTypeSwiftModules) // downstream change
1018+
.Case(".lldbsummaries", lldb::eSectionTypeLLDBTypeSummaries)
10181019
.Default(eSectionTypeInvalid);
10191020
if (section_type != eSectionTypeInvalid)
10201021
return section_type;

lldb/source/Symbol/ObjectFile.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@ AddressClass ObjectFile::GetAddressClass(addr_t file_addr) {
358358
case eSectionTypeSwiftModules:
359359
case eSectionTypeDWARFGNUDebugAltLink:
360360
case eSectionTypeCTF:
361+
case eSectionTypeLLDBTypeSummaries:
361362
return AddressClass::eDebug;
362363
case eSectionTypeEHFrame:
363364
case eSectionTypeARMexidx:

lldb/source/Target/Target.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "lldb/Core/StructuredDataImpl.h"
2828
#include "lldb/Core/ValueObject.h"
2929
#include "lldb/Core/ValueObjectConstResult.h"
30+
#include "lldb/DataFormatters/DataVisualization.h"
3031
#include "lldb/Expression/DiagnosticManager.h"
3132
#include "lldb/Expression/ExpressionVariable.h"
3233
#include "lldb/Expression/REPL.h"
@@ -1438,6 +1439,76 @@ static void LoadScriptingResourceForModule(const ModuleSP &module_sp,
14381439
feedback_stream.GetData());
14391440
}
14401441

1442+
// Load type summaries embedded in the binary. These are type summaries provided
1443+
// by the authors of the code.
1444+
static void LoadTypeSummariesForModule(ModuleSP module_sp) {
1445+
auto *sections = module_sp->GetSectionList();
1446+
if (!sections)
1447+
return;
1448+
1449+
auto summaries_sp =
1450+
sections->FindSectionByType(eSectionTypeLLDBTypeSummaries, true);
1451+
if (!summaries_sp)
1452+
return;
1453+
1454+
Log *log = GetLog(LLDBLog::DataFormatters);
1455+
const char *module_name = module_sp->GetObjectName().GetCString();
1456+
1457+
TypeCategoryImplSP category;
1458+
DataVisualization::Categories::GetCategory(ConstString("default"), category);
1459+
1460+
// The type summary record is serialized as follows.
1461+
//
1462+
// Each record contains, in order:
1463+
// * Version number of the record format
1464+
// * The remaining size of the record
1465+
// * The size of the type identifier
1466+
// * The type identifier, either a type name, or a regex
1467+
// * The size of the summary string
1468+
// * The summary string
1469+
//
1470+
// Integers are encoded using ULEB.
1471+
//
1472+
// Strings are encoded with first a length (ULEB), then the string contents,
1473+
// and lastly a null terminator. The length includes the null.
1474+
1475+
DataExtractor extractor;
1476+
auto section_size = summaries_sp->GetSectionData(extractor);
1477+
lldb::offset_t offset = 0;
1478+
while (offset < section_size) {
1479+
uint64_t version = extractor.GetULEB128(&offset);
1480+
uint64_t record_size = extractor.GetULEB128(&offset);
1481+
if (version == 1) {
1482+
uint64_t type_size = extractor.GetULEB128(&offset);
1483+
llvm::StringRef type_name = extractor.GetCStr(&offset, type_size);
1484+
uint64_t summary_size = extractor.GetULEB128(&offset);
1485+
llvm::StringRef summary_string = extractor.GetCStr(&offset, summary_size);
1486+
if (!type_name.empty() && !summary_string.empty()) {
1487+
TypeSummaryImpl::Flags flags;
1488+
auto summary_sp =
1489+
std::make_shared<StringSummaryFormat>(flags, summary_string.data());
1490+
FormatterMatchType match_type = eFormatterMatchExact;
1491+
if (summary_string.front() == '^' && summary_string.back() == '$')
1492+
match_type = eFormatterMatchRegex;
1493+
category->AddTypeSummary(type_name, match_type, summary_sp);
1494+
LLDB_LOGF(log, "Loaded embedded type summary for '%s' from %s.",
1495+
type_name.data(), module_name);
1496+
} else {
1497+
if (type_name.empty())
1498+
LLDB_LOGF(log, "Missing string(s) in embedded type summary in %s.",
1499+
module_name);
1500+
}
1501+
} else {
1502+
// Skip unsupported record.
1503+
offset += record_size;
1504+
LLDB_LOGF(
1505+
log,
1506+
"Skipping unsupported embedded type summary of version %llu in %s.",
1507+
version, module_name);
1508+
}
1509+
}
1510+
}
1511+
14411512
void Target::ClearModules(bool delete_locations) {
14421513
ModulesDidUnload(m_images, delete_locations);
14431514
m_section_load_history.Clear();
@@ -1682,6 +1753,7 @@ void Target::ModulesDidLoad(ModuleList &module_list) {
16821753
for (size_t idx = 0; idx < num_images; ++idx) {
16831754
ModuleSP module_sp(module_list.GetModuleAtIndex(idx));
16841755
LoadScriptingResourceForModule(module_sp, this);
1756+
LoadTypeSummariesForModule(module_sp);
16851757
}
16861758
m_breakpoint_list.UpdateBreakpoints(module_list, true, false);
16871759
m_internal_breakpoint_list.UpdateBreakpoints(module_list, true, false);
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
C_SOURCES := main.c
2+
include Makefile.rules
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import lldb
2+
from lldbsuite.test.decorators import *
3+
from lldbsuite.test.lldbtest import *
4+
from lldbsuite.test import lldbutil
5+
6+
7+
class TestCase(TestBase):
8+
@skipUnlessDarwin
9+
def test(self):
10+
self.build()
11+
lldbutil.run_to_source_breakpoint(self, "break here", lldb.SBFileSpec("main.c"))
12+
self.expect("v player", substrs=['"Dirk" (41)'])
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#include <stdio.h>
2+
3+
struct Player {
4+
char *name;
5+
int number;
6+
};
7+
8+
__attribute__((used, section("__DATA_CONST,__lldbsummaries"))) unsigned char
9+
_Player_type_summary[] = "\x01" // version
10+
"\x25" // record size
11+
"\x07" // type name size
12+
"Player\0" // type name
13+
"\x1c" // summary string size
14+
"${var.name} (${var.number})"; // summary string
15+
16+
int main() {
17+
struct Player player;
18+
player.name = "Dirk";
19+
player.number = 41;
20+
puts("break here");
21+
return 0;
22+
}

0 commit comments

Comments
 (0)