Skip to content

Commit 1e51be8

Browse files
kastiglioneadrian-prantl
authored andcommitted
[lldb] Load embedded type summary section (swiftlang#7859) (swiftlang#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
1 parent 337936a commit 1e51be8

File tree

10 files changed

+121
-0
lines changed

10 files changed

+121
-0
lines changed

lldb/include/lldb/lldb-enumerations.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,7 @@ enum SectionType {
763763
eSectionTypeDWARFDebugLocListsDwo,
764764
eSectionTypeDWARFDebugTuIndex,
765765
eSectionTypeCTF,
766+
eSectionTypeLLDBTypeSummaries,
766767
eSectionTypeSwiftModules,
767768
};
768769

lldb/source/Core/Section.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ const char *Section::GetTypeAsCString() const {
147147
return "dwarf-gnu-debugaltlink";
148148
case eSectionTypeCTF:
149149
return "ctf";
150+
case eSectionTypeLLDBTypeSummaries:
151+
return "lldb-type-summaries";
150152
case eSectionTypeOther:
151153
return "regular";
152154
case eSectionTypeSwiftModules:
@@ -457,6 +459,7 @@ bool Section::ContainsOnlyDebugInfo() const {
457459
case eSectionTypeDWARFAppleObjC:
458460
case eSectionTypeDWARFGNUDebugAltLink:
459461
case eSectionTypeCTF:
462+
case eSectionTypeLLDBTypeSummaries:
460463
case eSectionTypeSwiftModules:
461464
return true;
462465
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1696,6 +1696,7 @@ static SectionType GetSectionTypeFromName(llvm::StringRef Name) {
16961696
.Case(".gnu_debugaltlink", eSectionTypeDWARFGNUDebugAltLink)
16971697
.Case(".gosymtab", eSectionTypeGoSymtab)
16981698
.Case(".text", eSectionTypeCode)
1699+
.Case(".lldbsummaries", lldb::eSectionTypeLLDBTypeSummaries)
16991700
.Case(".swift_ast", eSectionTypeSwiftModules)
17001701
.Default(eSectionTypeOther);
17011702
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,7 @@ AddressClass ObjectFileMachO::GetAddressClass(lldb::addr_t file_addr) {
12091209
case eSectionTypeDWARFAppleObjC:
12101210
case eSectionTypeDWARFGNUDebugAltLink:
12111211
case eSectionTypeCTF:
1212+
case eSectionTypeLLDBTypeSummaries:
12121213
case eSectionTypeSwiftModules:
12131214
return AddressClass::eDebug;
12141215

@@ -1484,6 +1485,7 @@ static lldb::SectionType GetSectionType(uint32_t flags,
14841485
static ConstString g_sect_name_data("__data");
14851486
static ConstString g_sect_name_go_symtab("__gosymtab");
14861487
static ConstString g_sect_name_ctf("__ctf");
1488+
static ConstString g_sect_name_lldb_summaries("__lldbsummaries");
14871489
static ConstString g_sect_name_swift_ast("__swift_ast");
14881490

14891491
if (section_name == g_sect_name_dwarf_debug_abbrev)
@@ -1564,6 +1566,8 @@ static lldb::SectionType GetSectionType(uint32_t flags,
15641566
return eSectionTypeGoSymtab;
15651567
if (section_name == g_sect_name_ctf)
15661568
return eSectionTypeCTF;
1569+
if (section_name == g_sect_name_lldb_summaries)
1570+
return lldb::eSectionTypeLLDBTypeSummaries;
15671571
if (section_name == g_sect_name_swift_ast)
15681572
return eSectionTypeSwiftModules;
15691573
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
@@ -1010,6 +1010,7 @@ SectionType ObjectFilePECOFF::GetSectionType(llvm::StringRef sect_name,
10101010
// .eh_frame can be truncated to 8 chars.
10111011
.Cases(".eh_frame", ".eh_fram", eSectionTypeEHFrame)
10121012
.Case(".gosymtab", eSectionTypeGoSymtab)
1013+
.Case(".lldbsummaries", lldb::eSectionTypeLLDBTypeSummaries)
10131014
.Case("swiftast", eSectionTypeSwiftModules)
10141015
.Default(eSectionTypeInvalid);
10151016
if (section_type != eSectionTypeInvalid)

lldb/source/Symbol/ObjectFile.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ AddressClass ObjectFile::GetAddressClass(addr_t file_addr) {
366366
case eSectionTypeDWARFAppleObjC:
367367
case eSectionTypeDWARFGNUDebugAltLink:
368368
case eSectionTypeCTF:
369+
case eSectionTypeLLDBTypeSummaries:
369370
case eSectionTypeSwiftModules:
370371
return AddressClass::eDebug;
371372
case eSectionTypeEHFrame:

lldb/source/Target/Target.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
#include "lldb/Core/Section.h"
2525
#include "lldb/Core/SourceManager.h"
2626
#include "lldb/Core/StructuredDataImpl.h"
27+
#include "lldb/Core/ValueObject.h"
28+
#include "lldb/Core/ValueObjectConstResult.h"
29+
#include "lldb/DataFormatters/DataVisualization.h"
2730
#include "lldb/Expression/DiagnosticManager.h"
2831
#include "lldb/Expression/ExpressionVariable.h"
2932
#include "lldb/Expression/REPL.h"
@@ -1538,6 +1541,76 @@ static void LoadScriptingResourceForModule(const ModuleSP &module_sp,
15381541
feedback_stream.GetData());
15391542
}
15401543

1544+
// Load type summaries embedded in the binary. These are type summaries provided
1545+
// by the authors of the code.
1546+
static void LoadTypeSummariesForModule(ModuleSP module_sp) {
1547+
auto *sections = module_sp->GetSectionList();
1548+
if (!sections)
1549+
return;
1550+
1551+
auto summaries_sp =
1552+
sections->FindSectionByType(eSectionTypeLLDBTypeSummaries, true);
1553+
if (!summaries_sp)
1554+
return;
1555+
1556+
Log *log = GetLog(LLDBLog::DataFormatters);
1557+
const char *module_name = module_sp->GetObjectName().GetCString();
1558+
1559+
TypeCategoryImplSP category;
1560+
DataVisualization::Categories::GetCategory(ConstString("default"), category);
1561+
1562+
// The type summary record is serialized as follows.
1563+
//
1564+
// Each record contains, in order:
1565+
// * Version number of the record format
1566+
// * The remaining size of the record
1567+
// * The size of the type identifier
1568+
// * The type identifier, either a type name, or a regex
1569+
// * The size of the summary string
1570+
// * The summary string
1571+
//
1572+
// Integers are encoded using ULEB.
1573+
//
1574+
// Strings are encoded with first a length (ULEB), then the string contents,
1575+
// and lastly a null terminator. The length includes the null.
1576+
1577+
DataExtractor extractor;
1578+
auto section_size = summaries_sp->GetSectionData(extractor);
1579+
lldb::offset_t offset = 0;
1580+
while (offset < section_size) {
1581+
uint64_t version = extractor.GetULEB128(&offset);
1582+
uint64_t record_size = extractor.GetULEB128(&offset);
1583+
if (version == 1) {
1584+
uint64_t type_size = extractor.GetULEB128(&offset);
1585+
llvm::StringRef type_name = extractor.GetCStr(&offset, type_size);
1586+
uint64_t summary_size = extractor.GetULEB128(&offset);
1587+
llvm::StringRef summary_string = extractor.GetCStr(&offset, summary_size);
1588+
if (!type_name.empty() && !summary_string.empty()) {
1589+
TypeSummaryImpl::Flags flags;
1590+
auto summary_sp =
1591+
std::make_shared<StringSummaryFormat>(flags, summary_string.data());
1592+
FormatterMatchType match_type = eFormatterMatchExact;
1593+
if (summary_string.front() == '^' && summary_string.back() == '$')
1594+
match_type = eFormatterMatchRegex;
1595+
category->AddTypeSummary(type_name, match_type, summary_sp);
1596+
LLDB_LOGF(log, "Loaded embedded type summary for '%s' from %s.",
1597+
type_name.data(), module_name);
1598+
} else {
1599+
if (type_name.empty())
1600+
LLDB_LOGF(log, "Missing string(s) in embedded type summary in %s.",
1601+
module_name);
1602+
}
1603+
} else {
1604+
// Skip unsupported record.
1605+
offset += record_size;
1606+
LLDB_LOGF(
1607+
log,
1608+
"Skipping unsupported embedded type summary of version %llu in %s.",
1609+
version, module_name);
1610+
}
1611+
}
1612+
}
1613+
15411614
void Target::ClearModules(bool delete_locations) {
15421615
ModulesDidUnload(m_images, delete_locations);
15431616
m_section_load_history.Clear();
@@ -1818,6 +1891,7 @@ void Target::ModulesDidLoad(ModuleList &module_list) {
18181891
for (size_t idx = 0; idx < num_images; ++idx) {
18191892
ModuleSP module_sp(module_list.GetModuleAtIndex(idx));
18201893
LoadScriptingResourceForModule(module_sp, this);
1894+
LoadTypeSummariesForModule(module_sp);
18211895
}
18221896
m_breakpoint_list.UpdateBreakpoints(module_list, true, false);
18231897
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)