Skip to content

Commit 2e8c627

Browse files
authored
[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 macros, but can be generated by any other means. rdar://115184658 (cherry picked from commit a614c4d)
1 parent 29dc529 commit 2e8c627

File tree

10 files changed

+119
-0
lines changed

10 files changed

+119
-0
lines changed

lldb/include/lldb/lldb-enumerations.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,7 @@ enum SectionType {
771771
eSectionTypeDWARFDebugLocListsDwo,
772772
eSectionTypeDWARFDebugTuIndex,
773773
eSectionTypeCTF,
774+
eSectionTypeLLDBTypeSummaries,
774775
eSectionTypeSwiftModules,
775776
};
776777

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
case eSectionTypeSwiftModules:
@@ -459,6 +461,7 @@ bool Section::ContainsOnlyDebugInfo() const {
459461
case eSectionTypeDWARFAppleObjC:
460462
case eSectionTypeDWARFGNUDebugAltLink:
461463
case eSectionTypeCTF:
464+
case eSectionTypeLLDBTypeSummaries:
462465
#ifdef LLDB_ENABLE_SWIFT
463466
case eSectionTypeSwiftModules:
464467
#endif

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1693,6 +1693,7 @@ static SectionType GetSectionTypeFromName(llvm::StringRef Name) {
16931693
.Case(".gnu_debugaltlink", eSectionTypeDWARFGNUDebugAltLink)
16941694
.Case(".gosymtab", eSectionTypeGoSymtab)
16951695
.Case(".text", eSectionTypeCode)
1696+
.Case(".lldbsummaries", lldb::eSectionTypeLLDBTypeSummaries)
16961697
.Case(".swift_ast", eSectionTypeSwiftModules)
16971698
.Default(eSectionTypeOther);
16981699
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,6 +1205,7 @@ AddressClass ObjectFileMachO::GetAddressClass(lldb::addr_t file_addr) {
12051205
case eSectionTypeDWARFAppleObjC:
12061206
case eSectionTypeDWARFGNUDebugAltLink:
12071207
case eSectionTypeCTF:
1208+
case eSectionTypeLLDBTypeSummaries:
12081209
case eSectionTypeSwiftModules:
12091210
return AddressClass::eDebug;
12101211

@@ -1482,6 +1483,7 @@ static lldb::SectionType GetSectionType(uint32_t flags,
14821483
static ConstString g_sect_name_data("__data");
14831484
static ConstString g_sect_name_go_symtab("__gosymtab");
14841485
static ConstString g_sect_name_ctf("__ctf");
1486+
static ConstString g_sect_name_lldb_summaries("__lldbsummaries");
14851487
static ConstString g_sect_name_swift_ast("__swift_ast");
14861488

14871489
if (section_name == g_sect_name_dwarf_debug_abbrev)
@@ -1562,6 +1564,8 @@ static lldb::SectionType GetSectionType(uint32_t flags,
15621564
return eSectionTypeGoSymtab;
15631565
if (section_name == g_sect_name_ctf)
15641566
return eSectionTypeCTF;
1567+
if (section_name == g_sect_name_lldb_summaries)
1568+
return lldb::eSectionTypeLLDBTypeSummaries;
15651569
if (section_name == g_sect_name_swift_ast)
15661570
return eSectionTypeSwiftModules;
15671571
if (section_name == g_sect_name_objc_data ||

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,7 @@ SectionType ObjectFilePECOFF::GetSectionType(llvm::StringRef sect_name,
10121012
// .eh_frame can be truncated to 8 chars.
10131013
.Cases(".eh_frame", ".eh_fram", eSectionTypeEHFrame)
10141014
.Case(".gosymtab", eSectionTypeGoSymtab)
1015+
.Case(".lldbsummaries", lldb::eSectionTypeLLDBTypeSummaries)
10151016
.Case("swiftast", eSectionTypeSwiftModules)
10161017
.Default(eSectionTypeInvalid);
10171018
if (section_type != eSectionTypeInvalid)

lldb/source/Symbol/ObjectFile.cpp

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

lldb/source/Target/Target.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "lldb/Core/StructuredDataImpl.h"
2727
#include "lldb/Core/ValueObject.h"
2828
#include "lldb/Core/ValueObjectConstResult.h"
29+
#include "lldb/DataFormatters/DataVisualization.h"
2930
#include "lldb/Expression/DiagnosticManager.h"
3031
#include "lldb/Expression/ExpressionVariable.h"
3132
#include "lldb/Expression/REPL.h"
@@ -1477,6 +1478,76 @@ static void LoadScriptingResourceForModule(const ModuleSP &module_sp,
14771478
feedback_stream.GetData());
14781479
}
14791480

1481+
// Load type summaries embedded in the binary. These are type summaries provided
1482+
// by the authors of the code.
1483+
static void LoadTypeSummariesForModule(ModuleSP module_sp) {
1484+
auto *sections = module_sp->GetSectionList();
1485+
if (!sections)
1486+
return;
1487+
1488+
auto summaries_sp =
1489+
sections->FindSectionByType(eSectionTypeLLDBTypeSummaries, true);
1490+
if (!summaries_sp)
1491+
return;
1492+
1493+
Log *log = GetLog(LLDBLog::DataFormatters);
1494+
const char *module_name = module_sp->GetObjectName().GetCString();
1495+
1496+
TypeCategoryImplSP category;
1497+
DataVisualization::Categories::GetCategory(ConstString("default"), category);
1498+
1499+
// The type summary record is serialized as follows.
1500+
//
1501+
// Each record contains, in order:
1502+
// * Version number of the record format
1503+
// * The remaining size of the record
1504+
// * The size of the type identifier
1505+
// * The type identifier, either a type name, or a regex
1506+
// * The size of the summary string
1507+
// * The summary string
1508+
//
1509+
// Integers are encoded using ULEB.
1510+
//
1511+
// Strings are encoded with first a length (ULEB), then the string contents,
1512+
// and lastly a null terminator. The length includes the null.
1513+
1514+
DataExtractor extractor;
1515+
auto section_size = summaries_sp->GetSectionData(extractor);
1516+
lldb::offset_t offset = 0;
1517+
while (offset < section_size) {
1518+
uint64_t version = extractor.GetULEB128(&offset);
1519+
uint64_t record_size = extractor.GetULEB128(&offset);
1520+
if (version == 1) {
1521+
uint64_t type_size = extractor.GetULEB128(&offset);
1522+
llvm::StringRef type_name = extractor.GetCStr(&offset, type_size);
1523+
uint64_t summary_size = extractor.GetULEB128(&offset);
1524+
llvm::StringRef summary_string = extractor.GetCStr(&offset, summary_size);
1525+
if (!type_name.empty() && !summary_string.empty()) {
1526+
TypeSummaryImpl::Flags flags;
1527+
auto summary_sp =
1528+
std::make_shared<StringSummaryFormat>(flags, summary_string.data());
1529+
FormatterMatchType match_type = eFormatterMatchExact;
1530+
if (summary_string.front() == '^' && summary_string.back() == '$')
1531+
match_type = eFormatterMatchRegex;
1532+
category->AddTypeSummary(type_name, match_type, summary_sp);
1533+
LLDB_LOGF(log, "Loaded embedded type summary for '%s' from %s.",
1534+
type_name.data(), module_name);
1535+
} else {
1536+
if (type_name.empty())
1537+
LLDB_LOGF(log, "Missing string(s) in embedded type summary in %s.",
1538+
module_name);
1539+
}
1540+
} else {
1541+
// Skip unsupported record.
1542+
offset += record_size;
1543+
LLDB_LOGF(
1544+
log,
1545+
"Skipping unsupported embedded type summary of version %llu in %s.",
1546+
version, module_name);
1547+
}
1548+
}
1549+
}
1550+
14801551
void Target::ClearModules(bool delete_locations) {
14811552
ModulesDidUnload(m_images, delete_locations);
14821553
m_section_load_history.Clear();
@@ -1721,6 +1792,7 @@ void Target::ModulesDidLoad(ModuleList &module_list) {
17211792
for (size_t idx = 0; idx < num_images; ++idx) {
17221793
ModuleSP module_sp(module_list.GetModuleAtIndex(idx));
17231794
LoadScriptingResourceForModule(module_sp, this);
1795+
LoadTypeSummariesForModule(module_sp);
17241796
}
17251797
m_breakpoint_list.UpdateBreakpoints(module_list, true, false);
17261798
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)