Skip to content

🍒[lldb] Highlight function names in backtraces #10556

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 28 commits into
base: swift/release/6.2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
a1663c3
[lldb][FormatEntity][NFCI] Refactor FunctionNameWithArgs into helper …
Michael137 Apr 10, 2025
e16cdd3
[lldb][Format][NFCI] Refactor CPlusPlusLanguage::GetFunctionDisplayNa…
Michael137 Apr 11, 2025
a719c49
[lldb][Language] Change GetFunctionDisplayName to take SymbolContext …
Michael137 Apr 13, 2025
34bc8be
[lldb][Format] Display only the inlined frame name in backtraces if a…
Michael137 Apr 13, 2025
1a2f2d5
[lldb][Format][NFC] Factor FunctionNameWithArgs case out into helper …
Michael137 Apr 13, 2025
7f1e988
[lldb][test] Fix NativePDB/inline_sites_live.cpp inlined frame format
Michael137 Apr 14, 2025
d2ebe63
[lldb][Format][NFC] Remove unused FormatEntity::FormatCString
Michael137 Apr 14, 2025
2b60e9c
[ItaniumDemangle] Add customizable printLeft/printRight APIs to Outpu…
Michael137 Apr 17, 2025
1025be0
[ItaniumDemangle][test] Add test-cases for ref-qualified member point…
Michael137 Apr 23, 2025
0226820
[lldb] Implement TrackingOutputBuffer to track demangled name informa…
Michael137 Apr 7, 2025
8e5e1b2
[lldb][Mangled] Add API to force re-demangling a Mangled object (#131…
Michael137 Mar 10, 2025
268253b
[lldb][Mangled] Retrieve and cache demangled name info (#131836)
Michael137 Apr 7, 2025
3ddde4c
[lldb][Format] Introduce new frame-format variables for function part…
Michael137 Apr 11, 2025
b4c1a18
[lldb][CPlusPlus] Add plugin.cplusplus.display.function-name-format s…
Michael137 Apr 14, 2025
7c147e0
[lldb] Remove redundant DemangledNameInfo::operator==
Michael137 Apr 25, 2025
5fc9e5c
[lldb] Fix MangledTest build failure
Michael137 Apr 25, 2025
004abd1
[ItaniumDemangle][NFC] Add getter to ObjCProtoName::getProtocol
Michael137 Apr 25, 2025
265cbb3
[lldb][NFC] Add missing newline between function definitions
Michael137 Apr 25, 2025
a0cc261
[lldb][test] MangledTest: don't use designated initializers
Michael137 Apr 25, 2025
42e1c5c
[lldb][test] Skip Objective-C FrameFormat tests on Windows
Michael137 Apr 26, 2025
f342292
[lldb][test] Fix/XFAIL FrameFormat tests on Windows
Michael137 Apr 26, 2025
166d3e0
[lldb][test] Make sure we compile FrameFormat tests with DWARF
Michael137 Apr 26, 2025
64688bb
[lldb][test] Un-XFAIL TestCxxFrameFormat.test for now
Michael137 Apr 26, 2025
dc6e033
[lldb][test] XFAIL FrameFormat tests on Windows again
Michael137 Apr 26, 2025
91e761c
[lldb][CPlusPLus] Make C++ frame-format work without debug-info
Michael137 Apr 25, 2025
a06d362
[lldb] Highlight basenames in backtraces instead of PC value
Michael137 Apr 25, 2025
885c46e
[lldb][test] XFAIL TestCxxFrameFormat.test for Windows target
Michael137 Apr 26, 2025
0685cec
[lldb][Swift][NFC] Adjust GetFunctionDisplayName to take SymbolContex…
Michael137 Apr 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 57 additions & 40 deletions libcxxabi/src/demangle/ItaniumDemangle.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,20 +278,11 @@ class Node {
}

void print(OutputBuffer &OB) const {
printLeft(OB);
OB.printLeft(*this);
if (RHSComponentCache != Cache::No)
printRight(OB);
OB.printRight(*this);
}

// Print the "left" side of this Node into OutputBuffer.
virtual void printLeft(OutputBuffer &) const = 0;

// Print the "right". This distinction is necessary to represent C++ types
// that appear on the RHS of their subtype, such as arrays or functions.
// Since most types don't have such a component, provide a default
// implementation.
virtual void printRight(OutputBuffer &) const {}

virtual std::string_view getBaseName() const { return {}; }

// Silence compiler warnings, this dtor will never be called.
Expand All @@ -300,6 +291,24 @@ class Node {
#ifndef NDEBUG
DEMANGLE_DUMP_METHOD void dump() const;
#endif

private:
friend class OutputBuffer;

// Print the "left" side of this Node into OutputBuffer.
//
// Note, should only be called from OutputBuffer implementations.
// Call \ref OutputBuffer::printLeft instead.
virtual void printLeft(OutputBuffer &) const = 0;

// Print the "right". This distinction is necessary to represent C++ types
// that appear on the RHS of their subtype, such as arrays or functions.
// Since most types don't have such a component, provide a default
// implementation.
//
// Note, should only be called from OutputBuffer implementations.
// Call \ref OutputBuffer::printRight instead.
virtual void printRight(OutputBuffer &) const {}
};

class NodeArray {
Expand Down Expand Up @@ -444,11 +453,11 @@ class QualType final : public Node {
}

void printLeft(OutputBuffer &OB) const override {
Child->printLeft(OB);
OB.printLeft(*Child);
printQuals(OB);
}

void printRight(OutputBuffer &OB) const override { Child->printRight(OB); }
void printRight(OutputBuffer &OB) const override { OB.printRight(*Child); }
};

class ConversionOperatorType final : public Node {
Expand Down Expand Up @@ -477,7 +486,7 @@ class PostfixQualifiedType final : public Node {
template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }

void printLeft(OutputBuffer &OB) const override {
Ty->printLeft(OB);
OB.printLeft(*Ty);
OB += Postfix;
}
};
Expand Down Expand Up @@ -563,7 +572,7 @@ struct AbiTagAttr : Node {
std::string_view getBaseName() const override { return Base->getBaseName(); }

void printLeft(OutputBuffer &OB) const override {
Base->printLeft(OB);
OB.printLeft(*Base);
OB += "[abi:";
OB += Tag;
OB += "]";
Expand All @@ -589,8 +598,6 @@ class ObjCProtoName : public Node {
const Node *Ty;
std::string_view Protocol;

friend class PointerType;

public:
ObjCProtoName(const Node *Ty_, std::string_view Protocol_)
: Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {}
Expand All @@ -602,6 +609,8 @@ class ObjCProtoName : public Node {
static_cast<const NameType *>(Ty)->getName() == "objc_object";
}

std::string_view getProtocol() const { return Protocol; }

void printLeft(OutputBuffer &OB) const override {
Ty->print(OB);
OB += "<";
Expand Down Expand Up @@ -630,7 +639,7 @@ class PointerType final : public Node {
// We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>.
if (Pointee->getKind() != KObjCProtoName ||
!static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
Pointee->printLeft(OB);
OB.printLeft(*Pointee);
if (Pointee->hasArray(OB))
OB += " ";
if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))
Expand All @@ -639,7 +648,7 @@ class PointerType final : public Node {
} else {
const auto *objcProto = static_cast<const ObjCProtoName *>(Pointee);
OB += "id<";
OB += objcProto->Protocol;
OB += objcProto->getProtocol();
OB += ">";
}
}
Expand All @@ -649,7 +658,7 @@ class PointerType final : public Node {
!static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))
OB += ")";
Pointee->printRight(OB);
OB.printRight(*Pointee);
}
}
};
Expand Down Expand Up @@ -715,7 +724,7 @@ class ReferenceType : public Node {
std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);
if (!Collapsed.second)
return;
Collapsed.second->printLeft(OB);
OB.printLeft(*Collapsed.second);
if (Collapsed.second->hasArray(OB))
OB += " ";
if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))
Expand All @@ -732,7 +741,7 @@ class ReferenceType : public Node {
return;
if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))
OB += ")";
Collapsed.second->printRight(OB);
OB.printRight(*Collapsed.second);
}
};

Expand All @@ -752,7 +761,7 @@ class PointerToMemberType final : public Node {
}

void printLeft(OutputBuffer &OB) const override {
MemberType->printLeft(OB);
OB.printLeft(*MemberType);
if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))
OB += "(";
else
Expand All @@ -764,7 +773,7 @@ class PointerToMemberType final : public Node {
void printRight(OutputBuffer &OB) const override {
if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))
OB += ")";
MemberType->printRight(OB);
OB.printRight(*MemberType);
}
};

Expand All @@ -784,7 +793,7 @@ class ArrayType final : public Node {
bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
bool hasArraySlow(OutputBuffer &) const override { return true; }

void printLeft(OutputBuffer &OB) const override { Base->printLeft(OB); }
void printLeft(OutputBuffer &OB) const override { OB.printLeft(*Base); }

void printRight(OutputBuffer &OB) const override {
if (OB.back() != ']')
Expand All @@ -793,7 +802,7 @@ class ArrayType final : public Node {
if (Dimension)
Dimension->print(OB);
OB += "]";
Base->printRight(OB);
OB.printRight(*Base);
}
};

Expand Down Expand Up @@ -828,15 +837,15 @@ class FunctionType final : public Node {
// by printing out the return types's left, then print our parameters, then
// finally print right of the return type.
void printLeft(OutputBuffer &OB) const override {
Ret->printLeft(OB);
OB.printLeft(*Ret);
OB += " ";
}

void printRight(OutputBuffer &OB) const override {
OB.printOpen();
Params.printWithComma(OB);
OB.printClose();
Ret->printRight(OB);
OB.printRight(*Ret);

if (CVQuals & QualConst)
OB += " const";
Expand Down Expand Up @@ -941,6 +950,8 @@ class FunctionEncoding final : public Node {
FunctionRefQual getRefQual() const { return RefQual; }
NodeArray getParams() const { return Params; }
const Node *getReturnType() const { return Ret; }
const Node *getAttrs() const { return Attrs; }
const Node *getRequires() const { return Requires; }

bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
bool hasFunctionSlow(OutputBuffer &) const override { return true; }
Expand All @@ -949,19 +960,21 @@ class FunctionEncoding final : public Node {

void printLeft(OutputBuffer &OB) const override {
if (Ret) {
Ret->printLeft(OB);
OB.printLeft(*Ret);
if (!Ret->hasRHSComponent(OB))
OB += " ";
}

Name->print(OB);
}

void printRight(OutputBuffer &OB) const override {
OB.printOpen();
Params.printWithComma(OB);
OB.printClose();

if (Ret)
Ret->printRight(OB);
OB.printRight(*Ret);

if (CVQuals & QualConst)
OB += " const";
Expand Down Expand Up @@ -1301,14 +1314,14 @@ class NonTypeTemplateParamDecl final : public Node {
template<typename Fn> void match(Fn F) const { F(Name, Type); }

void printLeft(OutputBuffer &OB) const override {
Type->printLeft(OB);
OB.printLeft(*Type);
if (!Type->hasRHSComponent(OB))
OB += " ";
}

void printRight(OutputBuffer &OB) const override {
Name->print(OB);
Type->printRight(OB);
OB.printRight(*Type);
}
};

Expand Down Expand Up @@ -1353,11 +1366,11 @@ class TemplateParamPackDecl final : public Node {
template<typename Fn> void match(Fn F) const { F(Param); }

void printLeft(OutputBuffer &OB) const override {
Param->printLeft(OB);
OB.printLeft(*Param);
OB += "...";
}

void printRight(OutputBuffer &OB) const override { Param->printRight(OB); }
void printRight(OutputBuffer &OB) const override { OB.printRight(*Param); }
};

/// An unexpanded parameter pack (either in the expression or type context). If
Expand Down Expand Up @@ -1424,13 +1437,13 @@ class ParameterPack final : public Node {
initializePackExpansion(OB);
size_t Idx = OB.CurrentPackIndex;
if (Idx < Data.size())
Data[Idx]->printLeft(OB);
OB.printLeft(*Data[Idx]);
}
void printRight(OutputBuffer &OB) const override {
initializePackExpansion(OB);
size_t Idx = OB.CurrentPackIndex;
if (Idx < Data.size())
Data[Idx]->printRight(OB);
OB.printRight(*Data[Idx]);
}
};

Expand Down Expand Up @@ -1588,13 +1601,13 @@ struct ForwardTemplateReference : Node {
if (Printing)
return;
ScopedOverride<bool> SavePrinting(Printing, true);
Ref->printLeft(OB);
OB.printLeft(*Ref);
}
void printRight(OutputBuffer &OB) const override {
if (Printing)
return;
ScopedOverride<bool> SavePrinting(Printing, true);
Ref->printRight(OB);
OB.printRight(*Ref);
}
};

Expand Down Expand Up @@ -1746,7 +1759,7 @@ class DtorName : public Node {

void printLeft(OutputBuffer &OB) const override {
OB += "~";
Base->printLeft(OB);
OB.printLeft(*Base);
}
};

Expand Down Expand Up @@ -2026,7 +2039,7 @@ class CastExpr : public Node {
{
ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
OB += "<";
To->printLeft(OB);
OB.printLeft(*To);
OB += ">";
}
OB.printOpen();
Expand Down Expand Up @@ -5946,6 +5959,10 @@ struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
Alloc>::AbstractManglingParser;
};

inline void OutputBuffer::printLeft(const Node &N) { N.printLeft(*this); }

inline void OutputBuffer::printRight(const Node &N) { N.printRight(*this); }

DEMANGLE_NAMESPACE_END

#ifdef _LIBCXXABI_COMPILER_CLANG
Expand Down
26 changes: 25 additions & 1 deletion libcxxabi/src/demangle/Utility.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@

DEMANGLE_NAMESPACE_BEGIN

class Node;

// Stream that AST nodes write their string representation into after the AST
// has been parsed.
class OutputBuffer {
Expand Down Expand Up @@ -79,10 +81,24 @@ class OutputBuffer {
OutputBuffer(const OutputBuffer &) = delete;
OutputBuffer &operator=(const OutputBuffer &) = delete;

virtual ~OutputBuffer() {}

operator std::string_view() const {
return std::string_view(Buffer, CurrentPosition);
}

/// Called by the demangler when printing the demangle tree. By
/// default calls into \c Node::print{Left|Right} but can be overriden
/// by clients to track additional state when printing the demangled name.
virtual void printLeft(const Node &N);
virtual void printRight(const Node &N);

/// Called when we write to this object anywhere other than the end.
virtual void notifyInsertion(size_t /*Position*/, size_t /*Count*/) {}

/// Called when we make the \c CurrentPosition of this object smaller.
virtual void notifyDeletion(size_t /*OldPos*/, size_t /*NewPos*/) {}

/// If a ParameterPackExpansion (or similar type) is encountered, the offset
/// into the pack that we're currently printing.
unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
Expand Down Expand Up @@ -126,6 +142,8 @@ class OutputBuffer {
std::memcpy(Buffer, &*R.begin(), Size);
CurrentPosition += Size;

notifyInsertion(/*Position=*/0, /*Count=*/Size);

return *this;
}

Expand Down Expand Up @@ -161,14 +179,20 @@ class OutputBuffer {
DEMANGLE_ASSERT(Pos <= CurrentPosition, "");
if (N == 0)
return;

grow(N);
std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos);
std::memcpy(Buffer + Pos, S, N);
CurrentPosition += N;

notifyInsertion(Pos, N);
}

size_t getCurrentPosition() const { return CurrentPosition; }
void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
void setCurrentPosition(size_t NewPos) {
notifyDeletion(CurrentPosition, NewPos);
CurrentPosition = NewPos;
}

char back() const {
DEMANGLE_ASSERT(CurrentPosition, "");
Expand Down
2 changes: 2 additions & 0 deletions libcxxabi/test/test_demangle.pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29662,6 +29662,8 @@ const char* cases[][2] =
{"_ZNKO1X1hEv", "X::h() const &&"},
// {"_Z1fM1XVKFivEMS_VFivEMS_KOFivE", "f(int (X::*)() const volatile, int (X::*)() volatile, int (X::*)() const &&)"},
// {"_Z1fM1XRFivEMS_OFivEMS_KOFivE", "f(int (X::*)() &, int (X::*)() &&, int (X::*)() const &&)"},
{"_Z1fM1XKFivOE", "f(int (X::*)() const &&)"},
{"_Z1fM1XKFivOEMS_FOKivEMS_VFS3_RS2_E", "f(int (X::*)() const &&, int const&& (X::*)(), int const&& (X::*)(int const&) volatile)"},
{"_ZN5test12f0ENS_1TILZNS_1xEEEE", "test1::f0(test1::T<test1::x>)"},
{"_ZN5test12f1ENS_2t1ILZNS_2f0EfEEE", "test1::f1(test1::t1<test1::f0(float)>)"},
{"_ZN5test22f1ENS_2t1IXadL_ZNS_2f0EfEEEE", "test2::f1(test2::t1<&test2::f0(float)>)"},
Expand Down
Loading