Skip to content

Commit e79596d

Browse files
[lldb] add function name syntax highlighting in Swift backtraces
1 parent 091662c commit e79596d

File tree

7 files changed

+1510
-31
lines changed

7 files changed

+1510
-31
lines changed

lldb/source/Core/Mangled.cpp

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,41 @@ void Mangled::SetValue(ConstString name) {
148148
}
149149
}
150150

151+
// BEGIN SWIFT
152+
#ifdef LLDB_ENABLE_SWIFT
153+
static ConstString GetSwiftDemangledStr(ConstString m_mangled,
154+
const SymbolContext *sc,
155+
ConstString &m_demangled) {
156+
const char *mangled_name = m_mangled.GetCString();
157+
Log *log = GetLog(LLDBLog::Demangle);
158+
LLDB_LOGF(log, "demangle swift: %s", mangled_name);
159+
auto [demangled, info] = SwiftLanguageRuntime::TrackedDemangleSymbolAsString(
160+
mangled_name, SwiftLanguageRuntime::eSimplified, sc);
161+
info.PrefixRange.second =
162+
std::min(info.BasenameRange.first, info.ArgumentsRange.first);
163+
info.SuffixRange.first =
164+
std::max(info.BasenameRange.second, info.ArgumentsRange.second);
165+
info.SuffixRange.second = demangled.length();
166+
167+
// Don't cache the demangled name the function isn't available yet.
168+
if (!sc || !sc->function) {
169+
LLDB_LOGF(log, "demangle swift: %s -> \"%s\" (not cached)", mangled_name,
170+
demangled.c_str());
171+
return ConstString(demangled);
172+
}
173+
if (demangled.empty()) {
174+
LLDB_LOGF(log, "demangle swift: %s -> error: failed to demangle",
175+
mangled_name);
176+
} else {
177+
LLDB_LOGF(log, "demangle swift: %s -> \"%s\"", mangled_name,
178+
demangled.c_str());
179+
m_demangled.SetStringWithMangledCounterpart(demangled, m_mangled);
180+
}
181+
return m_demangled;
182+
}
183+
#endif // LLDB_ENABLE_SWIFT
184+
// END SWIFT
185+
151186
// Local helpers for different demangling implementations.
152187
static char *GetMSVCDemangledStr(llvm::StringRef M) {
153188
char *demangled_cstr = llvm::microsoftDemangle(
@@ -349,28 +384,7 @@ ConstString Mangled::GetDemangledNameImpl(bool force, // BEGIN SWIFT
349384
// Demangling a swift name requires the swift compiler. This is
350385
// explicitly unsupported on llvm.org.
351386
#ifdef LLDB_ENABLE_SWIFT
352-
{
353-
const char *mangled_name = m_mangled.GetCString();
354-
Log *log = GetLog(LLDBLog::Demangle);
355-
LLDB_LOGF(log, "demangle swift: %s", mangled_name);
356-
std::string demangled(SwiftLanguageRuntime::DemangleSymbolAsString(
357-
mangled_name, SwiftLanguageRuntime::eTypeName, sc));
358-
// Don't cache the demangled name the function isn't available yet.
359-
if (!sc || !sc->function) {
360-
LLDB_LOGF(log, "demangle swift: %s -> \"%s\" (not cached)", mangled_name,
361-
demangled.c_str());
362-
return ConstString(demangled);
363-
}
364-
if (demangled.empty()) {
365-
LLDB_LOGF(log, "demangle swift: %s -> error: failed to demangle",
366-
mangled_name);
367-
} else {
368-
LLDB_LOGF(log, "demangle swift: %s -> \"%s\"", mangled_name,
369-
demangled.c_str());
370-
m_demangled.SetStringWithMangledCounterpart(demangled, m_mangled);
371-
}
372-
return m_demangled;
373-
}
387+
return GetSwiftDemangledStr(m_mangled, sc, m_demangled);
374388
#endif // LLDB_ENABLE_SWIFT
375389
break;
376390
case eManglingSchemeNone:

lldb/source/Plugins/Language/Swift/SwiftLanguage.cpp

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1896,21 +1896,96 @@ SwiftLanguage::GetDemangledFunctionNameWithoutArguments(Mangled mangled) const {
18961896

18971897
static std::optional<llvm::StringRef>
18981898
GetDemangledBasename(const SymbolContext &sc) {
1899-
return std::nullopt;
1899+
Mangled mangled = sc.GetPossiblyInlinedFunctionName();
1900+
if (!mangled)
1901+
return std::nullopt;
1902+
1903+
auto demangled_name = mangled.GetDemangledName().GetStringRef();
1904+
if (demangled_name.empty())
1905+
return std::nullopt;
1906+
1907+
const std::optional<DemangledNameInfo> &info = mangled.GetDemangledInfo();
1908+
if (!info)
1909+
return std::nullopt;
1910+
1911+
// Function without a basename is nonsense.
1912+
if (!info->hasBasename())
1913+
return std::nullopt;
1914+
1915+
return demangled_name.slice(info->BasenameRange.first,
1916+
info->BasenameRange.second);
19001917
}
19011918

19021919
static std::optional<llvm::StringRef>
19031920
GetDemangledFunctionPrefix(const SymbolContext &sc) {
1904-
return std::nullopt;
1921+
Mangled mangled = sc.GetPossiblyInlinedFunctionName();
1922+
if (!mangled)
1923+
return std::nullopt;
1924+
1925+
auto demangled_name = mangled.GetDemangledName().GetStringRef();
1926+
if (demangled_name.empty())
1927+
return std::nullopt;
1928+
1929+
const std::optional<DemangledNameInfo> &info = mangled.GetDemangledInfo();
1930+
if (!info)
1931+
return std::nullopt;
1932+
1933+
// Function without a basename is nonsense.
1934+
if (!info->hasBasename())
1935+
return std::nullopt;
1936+
1937+
return demangled_name.slice(info->PrefixRange.first,
1938+
info->PrefixRange.second);
19051939
}
19061940

19071941
static std::optional<llvm::StringRef>
19081942
GetDemangledFunctionSuffix(const SymbolContext &sc) {
1909-
return std::nullopt;
1943+
Mangled mangled = sc.GetPossiblyInlinedFunctionName();
1944+
if (!mangled)
1945+
return std::nullopt;
1946+
1947+
auto demangled_name = mangled.GetDemangledName().GetStringRef();
1948+
if (demangled_name.empty())
1949+
return std::nullopt;
1950+
1951+
const std::optional<DemangledNameInfo> &info = mangled.GetDemangledInfo();
1952+
if (!info)
1953+
return std::nullopt;
1954+
1955+
// Function without a basename is nonsense.
1956+
if (!info->hasBasename())
1957+
return std::nullopt;
1958+
1959+
return demangled_name.slice(info->SuffixRange.first,
1960+
info->SuffixRange.second);
19101961
}
19111962

19121963
static bool PrintDemangledArgumentList(Stream &s, const SymbolContext &sc) {
1913-
return false;
1964+
assert(sc.symbol);
1965+
1966+
Mangled mangled = sc.GetPossiblyInlinedFunctionName();
1967+
if (!mangled)
1968+
return false;
1969+
1970+
auto demangled_name = mangled.GetDemangledName().GetStringRef();
1971+
if (demangled_name.empty())
1972+
return false;
1973+
1974+
const std::optional<DemangledNameInfo> &info = mangled.GetDemangledInfo();
1975+
if (!info)
1976+
return false;
1977+
1978+
// Function without a basename is nonsense.
1979+
if (!info->hasBasename())
1980+
return false;
1981+
1982+
if (info->ArgumentsRange.second < info->ArgumentsRange.first)
1983+
return false;
1984+
1985+
s << demangled_name.slice(info->ArgumentsRange.first,
1986+
info->ArgumentsRange.second);
1987+
1988+
return true;
19141989
}
19151990

19161991
static VariableListSP GetFunctionVariableList(const SymbolContext &sc) {
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
//===-- SwiftMangled.h ------------------------------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef liblldb_SwiftMangled_h_
14+
#define liblldb_SwiftMangled_h_
15+
16+
#include "lldb/Core/DemangledNameInfo.h"
17+
#include "swift/Demangling/Demangle.h"
18+
19+
using namespace swift::Demangle;
20+
21+
class TrackingNodePrinter : public NodePrinter {
22+
public:
23+
TrackingNodePrinter(DemangleOptions options) : NodePrinter(options) {}
24+
25+
lldb_private::DemangledNameInfo takeInfo() { return std::move(info); }
26+
27+
private:
28+
lldb_private::DemangledNameInfo info;
29+
std::optional<unsigned> parametersDepth;
30+
31+
void startName() {
32+
if (!info.hasBasename())
33+
info.BasenameRange.first = getStreamLength();
34+
}
35+
36+
void endName() {
37+
if (!info.hasBasename())
38+
info.BasenameRange.second = getStreamLength();
39+
}
40+
41+
void startParameters(unsigned depth) {
42+
if (parametersDepth || !info.hasBasename() || info.hasArguments()) {
43+
return;
44+
}
45+
info.ArgumentsRange.first = getStreamLength();
46+
parametersDepth = depth;
47+
}
48+
49+
void endParameters(unsigned depth) {
50+
if (!parametersDepth || *parametersDepth != depth || info.hasArguments()) {
51+
return;
52+
}
53+
info.ArgumentsRange.second = getStreamLength();
54+
}
55+
56+
bool shouldTrackNameRange(NodePointer Node) const {
57+
switch (Node->getKind()) {
58+
case Node::Kind::Function:
59+
case Node::Kind::Constructor:
60+
case Node::Kind::Allocator:
61+
case Node::Kind::ExplicitClosure:
62+
return true;
63+
default:
64+
return false;
65+
}
66+
}
67+
68+
void printFunctionName(bool hasName, llvm::StringRef &OverwriteName,
69+
llvm::StringRef &ExtraName, bool MultiWordName,
70+
int &ExtraIndex, NodePointer Entity,
71+
unsigned int depth) override {
72+
if (shouldTrackNameRange(Entity))
73+
startName();
74+
NodePrinter::printFunctionName(hasName, OverwriteName, ExtraName,
75+
MultiWordName, ExtraIndex, Entity, depth);
76+
if (shouldTrackNameRange(Entity))
77+
endName();
78+
}
79+
80+
void printFunctionParameters(NodePointer LabelList, NodePointer ParameterType,
81+
unsigned depth, bool showTypes) override {
82+
startParameters(depth);
83+
NodePrinter::printFunctionParameters(LabelList, ParameterType, depth,
84+
showTypes);
85+
endParameters(depth);
86+
}
87+
};
88+
89+
#endif // liblldb_SwiftMangled_h_

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,11 +200,17 @@ class SwiftLanguageRuntime : public LanguageRuntime {
200200
IsSwiftAsyncAwaitResumePartialFunctionSymbol(llvm::StringRef name);
201201

202202
enum DemangleMode { eSimplified, eTypeName, eDisplayTypeName };
203+
203204
static std::string
204205
DemangleSymbolAsString(llvm::StringRef symbol, DemangleMode mode,
205206
const SymbolContext *sc = nullptr,
206207
const ExecutionContext *exe_ctx = nullptr);
207208

209+
static std::pair<std::string, DemangledNameInfo>
210+
TrackedDemangleSymbolAsString(llvm::StringRef symbol, DemangleMode mode,
211+
const SymbolContext *sc = nullptr,
212+
const ExecutionContext *exe_ctx = nullptr);
213+
208214
static std::string GetParentNameIfClosure(llvm::StringRef mangled_name);
209215

210216
/// Demangle a symbol to a swift::Demangle node tree.
@@ -885,6 +891,11 @@ class SwiftLanguageRuntime : public LanguageRuntime {
885891

886892
/// Swift native NSError isa.
887893
std::optional<lldb::addr_t> m_SwiftNativeNSErrorISA;
894+
895+
static std::pair<std::string, std::optional<DemangledNameInfo>>
896+
DemangleSymbolAsString(llvm::StringRef symbol, DemangleMode mode,
897+
bool tracking, const SymbolContext *sc,
898+
const ExecutionContext *exe_ctx);
888899
};
889900

890901
/// The target specific register numbers used for async unwinding.

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeNames.cpp

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "SwiftLanguageRuntime.h"
1616

1717
#include "lldb/Breakpoint/StoppointCallbackContext.h"
18+
#include "lldb/Core/DemangledNameInfo.h"
1819
#include "lldb/Symbol/Block.h"
1920
#include "lldb/Symbol/CompileUnit.h"
2021
#include "lldb/Symbol/VariableList.h"
@@ -28,6 +29,7 @@
2829
#include "swift/Demangling/Demangle.h"
2930
#include "swift/Demangling/Demangler.h"
3031

32+
#include "Plugins/Language/Swift/SwiftMangled.h"
3133
#include "Plugins/Process/Utility/RegisterContext_x86.h"
3234
#include "Utility/ARM64_DWARF_Registers.h"
3335
#include "swift/Demangling/ManglingFlavor.h"
@@ -816,9 +818,11 @@ void SwiftLanguageRuntime::GetGenericParameterNamesForFunction(
816818
}
817819
}
818820

819-
std::string SwiftLanguageRuntime::DemangleSymbolAsString(
820-
llvm::StringRef symbol, DemangleMode mode, const SymbolContext *sc,
821-
const ExecutionContext *exe_ctx) {
821+
std::pair<std::string, std::optional<DemangledNameInfo>>
822+
SwiftLanguageRuntime::DemangleSymbolAsString(llvm::StringRef symbol,
823+
DemangleMode mode, bool tracking,
824+
const SymbolContext *sc,
825+
const ExecutionContext *exe_ctx) {
822826
bool did_init = false;
823827
llvm::DenseMap<ArchetypePath, llvm::StringRef> dict;
824828
swift::Demangle::DemangleOptions options;
@@ -863,7 +867,7 @@ std::string SwiftLanguageRuntime::DemangleSymbolAsString(
863867
return swift::Demangle::genericParameterName(depth, index);
864868
};
865869
} else {
866-
// Print generic generic parameter names.
870+
// Print generic parameter names.
867871
options.GenericParameterName = [&](uint64_t depth, uint64_t index) {
868872
std::string name;
869873
{
@@ -873,7 +877,29 @@ std::string SwiftLanguageRuntime::DemangleSymbolAsString(
873877
return name;
874878
};
875879
}
876-
return swift::Demangle::demangleSymbolAsString(symbol, options);
880+
if (tracking) {
881+
TrackingNodePrinter printer = TrackingNodePrinter(options);
882+
swift::Demangle::demangleSymbolAsString(symbol, &printer);
883+
return std::pair<std::string, std::optional<DemangledNameInfo>>(
884+
printer.takeString(), printer.takeInfo());
885+
}
886+
return std::pair<std::string, std::optional<DemangledNameInfo>>(
887+
swift::Demangle::demangleSymbolAsString(symbol, options), std::nullopt);
888+
}
889+
890+
std::string SwiftLanguageRuntime::DemangleSymbolAsString(
891+
llvm::StringRef symbol, DemangleMode mode, const SymbolContext *sc,
892+
const ExecutionContext *exe_ctx) {
893+
return DemangleSymbolAsString(symbol, mode, false, sc, exe_ctx).first;
894+
}
895+
896+
std::pair<std::string, DemangledNameInfo>
897+
SwiftLanguageRuntime::TrackedDemangleSymbolAsString(
898+
llvm::StringRef symbol, DemangleMode mode, const SymbolContext *sc,
899+
const ExecutionContext *exe_ctx) {
900+
auto demangledData = DemangleSymbolAsString(symbol, mode, true, sc, exe_ctx);
901+
return std::pair<std::string, DemangledNameInfo>(demangledData.first,
902+
*demangledData.second);
877903
}
878904

879905
swift::Demangle::NodePointer

lldb/unittests/Core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ add_lldb_unittest(LLDBCoreTests
1111
RichManglingContextTest.cpp
1212
SourceLocationSpecTest.cpp
1313
SourceManagerTest.cpp
14+
SwiftDemanglingPartsTest.cpp
1415
UniqueCStringMapTest.cpp
1516

1617
LINK_LIBS

0 commit comments

Comments
 (0)