Skip to content

Commit c9a4d24

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 74e1554 commit c9a4d24

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
@@ -761,6 +761,7 @@ enum SectionType {
761761
eSectionTypeDWARFDebugLocListsDwo,
762762
eSectionTypeDWARFDebugTuIndex,
763763
eSectionTypeCTF,
764+
eSectionTypeLLDBTypeSummaries,
764765
eSectionTypeSwiftModules,
765766
};
766767

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
@@ -1678,6 +1678,7 @@ static SectionType GetSectionTypeFromName(llvm::StringRef Name) {
16781678
.Case(".gnu_debugaltlink", eSectionTypeDWARFGNUDebugAltLink)
16791679
.Case(".gosymtab", eSectionTypeGoSymtab)
16801680
.Case(".text", eSectionTypeCode)
1681+
.Case(".lldbsummaries", lldb::eSectionTypeLLDBTypeSummaries)
16811682
.Case(".swift_ast", eSectionTypeSwiftModules)
16821683
.Default(eSectionTypeOther);
16831684
}

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: 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"
@@ -1537,6 +1538,76 @@ static void LoadScriptingResourceForModule(const ModuleSP &module_sp,
15371538
feedback_stream.GetData());
15381539
}
15391540

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