Skip to content

🍒 [LLDB] Refactor demangler range tracking #10767

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

Merged
Changes from all commits
Commits
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
5 changes: 4 additions & 1 deletion lldb/docs/use/formatting.rst
Original file line number Diff line number Diff line change
@@ -91,7 +91,9 @@ A complete list of currently supported format string variables is listed below:
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``function.basename`` | The basename of the current function depending on the frame's language. E.g., for C++ the basename for ``void ns::foo<float>::bar<int>(int) const`` is ``bar``. |
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``function.scope`` | The scope qualifiers of the current function depending on the frame's language. E.g., for C++ the scope for ``void ns::foo<float>::bar<int>(int) const`` is ``ns::foo<float>``. |
| ``function.prefix`` | Any prefix added to the demangled function name of the current function. This depends on the frame's language. E.g., for C++ the prefix will always be empty. |
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``function.scope`` | The scope qualifiers of the current function depending on the frame's language. E.g., for C++ the scope for ``void ns::foo<float>::bar<int>(int) const`` is ``ns::foo<float>``. |
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``function.template-arguments`` | The template arguments of the current function depending on the frame's language. E.g., for C++ the template arguments for ``void ns::foo<float>::bar<int>(int) const`` are ``<float>``. |
+---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
@@ -325,6 +327,7 @@ _____________________
The function names displayed in backtraces/``frame info``/``thread info`` are the demangled names of functions. On some platforms (like ones using Itanium the mangling scheme), LLDB supports decomposing these names into fine-grained components. These are currently:

- ``${function.return-left}``
- ``${function.prefix}``
- ``${function.scope}``
- ``${function.basename}``
- ``${function.template-arguments}``
12 changes: 11 additions & 1 deletion lldb/include/lldb/Core/DemangledNameInfo.h
Original file line number Diff line number Diff line change
@@ -39,7 +39,7 @@ struct DemangledNameInfo {
/// \endcode
std::pair<size_t, size_t> ScopeRange;

/// Indicates the [start, end) of the function argument lits.
/// Indicates the [start, end) of the function argument list.
/// E.g.,
/// \code{.cpp}
/// int (*getFunc<float>(float, double))(int, int)
@@ -59,6 +59,16 @@ struct DemangledNameInfo {
/// \endcode
std::pair<size_t, size_t> QualifiersRange;

/// Indicates the [start, end) of the function's prefix. This is a
/// catch-all range for anything that is not tracked by the rest of
/// the pairs.
std::pair<size_t, size_t> PrefixRange;

/// Indicates the [start, end) of the function's suffix. This is a
/// catch-all range for anything that is not tracked by the rest of
/// the pairs.
std::pair<size_t, size_t> SuffixRange;

/// Returns \c true if this object holds a valid basename range.
bool hasBasename() const {
return BasenameRange.second > BasenameRange.first &&
1 change: 1 addition & 0 deletions lldb/include/lldb/Core/FormatEntity.h
Original file line number Diff line number Diff line change
@@ -88,6 +88,7 @@ struct Entry {
FunctionNameWithArgs,
FunctionNameNoArgs,
FunctionMangledName,
FunctionPrefix,
FunctionScope,
FunctionBasename,
FunctionTemplateArguments,
3 changes: 3 additions & 0 deletions lldb/source/Core/FormatEntity.cpp
Original file line number Diff line number Diff line change
@@ -124,6 +124,7 @@ constexpr Definition g_function_child_entries[] = {
Definition("initial-function", EntryType::FunctionInitial),
Definition("changed", EntryType::FunctionChanged),
Definition("is-optimized", EntryType::FunctionIsOptimized),
Definition("prefix", EntryType::FunctionPrefix),
Definition("scope", EntryType::FunctionScope),
Definition("basename", EntryType::FunctionBasename),
Definition("template-arguments", EntryType::FunctionTemplateArguments),
@@ -385,6 +386,7 @@ const char *FormatEntity::Entry::TypeToCString(Type t) {
ENUM_TO_CSTR(FunctionNameWithArgs);
ENUM_TO_CSTR(FunctionNameNoArgs);
ENUM_TO_CSTR(FunctionMangledName);
ENUM_TO_CSTR(FunctionPrefix);
ENUM_TO_CSTR(FunctionScope);
ENUM_TO_CSTR(FunctionBasename);
ENUM_TO_CSTR(FunctionTemplateArguments);
@@ -1843,6 +1845,7 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
return true;
}

case Entry::Type::FunctionPrefix:
case Entry::Type::FunctionScope:
case Entry::Type::FunctionBasename:
case Entry::Type::FunctionTemplateArguments:
2 changes: 2 additions & 0 deletions lldb/source/Core/Mangled.cpp
Original file line number Diff line number Diff line change
@@ -181,6 +181,8 @@ GetItaniumDemangledStr(const char *M) {

TrackingOutputBuffer OB(demangled_cstr, demangled_size);
demangled_cstr = ipd.finishDemangle(&OB);
OB.NameInfo.SuffixRange.first = OB.NameInfo.QualifiersRange.second;
OB.NameInfo.SuffixRange.second = std::string_view(OB).size();
info = std::move(OB.NameInfo);

assert(demangled_cstr &&
Original file line number Diff line number Diff line change
@@ -374,8 +374,8 @@ GetDemangledFunctionSuffix(const SymbolContext &sc) {
if (!info->hasBasename())
return std::nullopt;

return demangled_name.slice(info->QualifiersRange.second,
llvm::StringRef::npos);
return demangled_name.slice(info->SuffixRange.first,
info->SuffixRange.second);
}

static bool PrintDemangledArgumentList(Stream &s, const SymbolContext &sc) {
24 changes: 24 additions & 0 deletions lldb/test/Shell/Settings/TestFrameFormatFunctionPrefix.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Check that we have an appropriate fallback for ${function.prefix} in languages that
# don't implement this frame format variable (in this case Objective-C).
#
# RUN: split-file %s %t
# RUN: %clang_host -g -gdwarf %t/main.m -o %t.objc.out
# RUN: %lldb -x -b -s %t/commands.input %t.objc.out -o exit 2>&1 \
# RUN: | FileCheck %s

#--- main.m

int func() {}
int bar() { func(); }

int main() { return bar(); }

#--- commands.input
settings set -f frame-format "custom-frame '${function.prefix}'\n"
break set -n bar

run
bt

# CHECK: bt
# CHECK-NOT: custom-frame
62 changes: 46 additions & 16 deletions lldb/unittests/Core/MangledTest.cpp
Original file line number Diff line number Diff line change
@@ -414,114 +414,144 @@ DemanglingPartsTestCase g_demangling_parts_test_cases[] = {
// clang-format off
{ "_ZNVKO3BarIN2ns3QuxIiEEE1CIPFi3FooIS_IiES6_EEE6methodIS6_EENS5_IT_SC_E5InnerIiEESD_SD_",
{ /*.BasenameRange=*/{92, 98}, /*.ScopeRange=*/{36, 92}, /*.ArgumentsRange=*/{ 108, 158 },
/*.QualifiersRange=*/{158, 176} },
/*.QualifiersRange=*/{158, 176}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
/*.basename=*/"method",
/*.scope=*/"Bar<ns::Qux<int>>::C<int (*)(Foo<Bar<int>, Bar<int>>)>::",
/*.qualifiers=*/" const volatile &&"
},
{ "_Z7getFuncIfEPFiiiET_",
{ /*.BasenameRange=*/{6, 13}, /*.ScopeRange=*/{6, 6}, /*.ArgumentsRange=*/{ 20, 27 }, /*.QualifiersRange=*/{38, 38} },
{ /*.BasenameRange=*/{6, 13}, /*.ScopeRange=*/{6, 6}, /*.ArgumentsRange=*/{ 20, 27 },
/*.QualifiersRange=*/{38, 38}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
/*.basename=*/"getFunc",
/*.scope=*/"",
/*.qualifiers=*/""
},
{ "_ZN1f1b1c1gEv",
{ /*.BasenameRange=*/{9, 10}, /*.ScopeRange=*/{0, 9}, /*.ArgumentsRange=*/{ 10, 12 },
/*.QualifiersRange=*/{12, 12} },
/*.QualifiersRange=*/{12, 12}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
/*.basename=*/"g",
/*.scope=*/"f::b::c::",
/*.qualifiers=*/""
},
{ "_ZN5test73fD1IiEEDTcmtlNS_1DEL_ZNS_1bEEEcvT__EES2_",
{ /*.BasenameRange=*/{45, 48}, /*.ScopeRange=*/{38, 45}, /*.ArgumentsRange=*/{ 53, 58 },
/*.QualifiersRange=*/{58, 58} },
/*.QualifiersRange=*/{58, 58}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
/*.basename=*/"fD1",
/*.scope=*/"test7::",
/*.qualifiers=*/""
},
{ "_ZN5test73fD1IiEEDTcmtlNS_1DEL_ZNS_1bINDT1cE1dEEEEEcvT__EES2_",
{ /*.BasenameRange=*/{61, 64}, /*.ScopeRange=*/{54, 61}, /*.ArgumentsRange=*/{ 69, 79 },
/*.QualifiersRange=*/{79, 79} },
/*.QualifiersRange=*/{79, 79}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
/*.basename=*/"fD1",
/*.scope=*/"test7::",
/*.qualifiers=*/""
},
{ "_ZN5test7INDT1cE1dINDT1cE1dEEEE3fD1INDT1cE1dINDT1cE1dEEEEEDTcmtlNS_1DEL_ZNS_1bINDT1cE1dEEEEEcvT__EES2_",
{ /*.BasenameRange=*/{120, 123}, /*.ScopeRange=*/{81, 120}, /*.ArgumentsRange=*/{ 155, 168 },
/*.QualifiersRange=*/{168, 168} },
/*.QualifiersRange=*/{168, 168}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
/*.basename=*/"fD1",
/*.scope=*/"test7<decltype(c)::d<decltype(c)::d>>::",
/*.qualifiers=*/""
},
{ "_ZN8nlohmann16json_abi_v3_11_310basic_jsonINSt3__13mapENS2_6vectorENS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbxydS8_NS0_14adl_serializerENS4_IhNS8_IhEEEEvE5parseIRA29_KcEESE_OT_NS2_8functionIFbiNS0_6detail13parse_event_tERSE_EEEbb",
{ /*.BasenameRange=*/{687, 692}, /*.ScopeRange=*/{343, 687}, /*.ArgumentsRange=*/{ 713, 1174 },
/*.QualifiersRange=*/{1174, 1174} },
/*.QualifiersRange=*/{1174, 1174}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
/*.basename=*/"parse",
/*.scope=*/"nlohmann::json_abi_v3_11_3::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, bool, long long, unsigned long long, double, std::__1::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::__1::vector<unsigned char, std::__1::allocator<unsigned char>>, void>::",
/*.qualifiers=*/""
},
{ "_ZN8nlohmann16json_abi_v3_11_310basic_jsonINSt3__13mapENS2_6vectorENS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbxydS8_NS0_14adl_serializerENS4_IhNS8_IhEEEEvEC1EDn",
{ /*.BasenameRange=*/{344, 354}, /*.ScopeRange=*/{0, 344}, /*.ArgumentsRange=*/{ 354, 370 },
/*.QualifiersRange=*/{370, 370} },
/*.QualifiersRange=*/{370, 370}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
/*.basename=*/"basic_json",
/*.scope=*/"nlohmann::json_abi_v3_11_3::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, bool, long long, unsigned long long, double, std::__1::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::__1::vector<unsigned char, std::__1::allocator<unsigned char>>, void>::",
/*.qualifiers=*/""
},
{ "_Z3fppIiEPFPFvvEiEf",
{ /*.BasenameRange=*/{10, 13}, /*.ScopeRange=*/{10, 10}, /*.ArgumentsRange=*/{ 18, 25 }, /*.QualifiersRange=*/{34,34} },
{ /*.BasenameRange=*/{10, 13}, /*.ScopeRange=*/{10, 10}, /*.ArgumentsRange=*/{ 18, 25 },
/*.QualifiersRange=*/{34,34}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
/*.basename=*/"fpp",
/*.scope=*/"",
/*.qualifiers=*/""
},
{ "_Z3fppIiEPFPFvvEN2ns3FooIiEEEf",
{ /*.BasenameRange=*/{10, 13}, /*.ScopeRange=*/{10, 10}, /*.ArgumentsRange=*/{ 18, 25 },
/*.QualifiersRange=*/{43, 43} },
/*.QualifiersRange=*/{43, 43}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
/*.basename=*/"fpp",
/*.scope=*/"",
/*.qualifiers=*/""
},
{ "_Z3fppIiEPFPFvPFN2ns3FooIiEENS2_3BarIfE3QuxEEEPFS2_S2_EEf",
{ /*.BasenameRange=*/{10, 13}, /*.ScopeRange=*/{10, 10}, /*.ArgumentsRange=*/{ 18, 25 },
/*.QualifiersRange=*/{108, 108} },
/*.QualifiersRange=*/{108, 108}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
/*.basename=*/"fpp",
/*.scope=*/"",
/*.qualifiers=*/""
},
{ "_ZN2ns8HasFuncsINS_3FooINS1_IiE3BarIfE3QuxEEEE3fppIiEEPFPFvvEiEf",
{ /*.BasenameRange=*/{64, 67}, /*.ScopeRange=*/{10, 64}, /*.ArgumentsRange=*/{ 72, 79 },
/*.QualifiersRange=*/{88, 88} },
/*.QualifiersRange=*/{88, 88}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
/*.basename=*/"fpp",
/*.scope=*/"ns::HasFuncs<ns::Foo<ns::Foo<int>::Bar<float>::Qux>>::",
/*.qualifiers=*/""
},
{ "_ZN2ns8HasFuncsINS_3FooINS1_IiE3BarIfE3QuxEEEE3fppIiEEPFPFvvES2_Ef",
{ /*.BasenameRange=*/{64, 67}, /*.ScopeRange=*/{10, 64}, /*.ArgumentsRange=*/{ 72, 79 },
/*.QualifiersRange=*/{97, 97} },
/*.QualifiersRange=*/{97, 97}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
/*.basename=*/"fpp",
/*.scope=*/"ns::HasFuncs<ns::Foo<ns::Foo<int>::Bar<float>::Qux>>::",
/*.qualifiers=*/"",
},
{ "_ZN2ns8HasFuncsINS_3FooINS1_IiE3BarIfE3QuxEEEE3fppIiEEPFPFvPFS2_S5_EEPFS2_S2_EEf",
{ /*.BasenameRange=*/{64, 67}, /*.ScopeRange=*/{10, 64}, /*.ArgumentsRange=*/{ 72, 79 },
/*.QualifiersRange=*/{162, 162} },
/*.QualifiersRange=*/{162, 162}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
/*.basename=*/"fpp",
/*.scope=*/"ns::HasFuncs<ns::Foo<ns::Foo<int>::Bar<float>::Qux>>::",
/*.qualifiers=*/"",
},
{ "_ZNKO2ns3ns23Bar3fooIiEEPFPFNS0_3FooIiEEiENS3_IfEEEi",
{ /*.BasenameRange=*/{37, 40}, /*.ScopeRange=*/{23, 37}, /*.ArgumentsRange=*/{ 45, 50 },
/*.QualifiersRange=*/{78, 87} },
/*.QualifiersRange=*/{78, 87}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
/*.basename=*/"foo",
/*.scope=*/"ns::ns2::Bar::",
/*.qualifiers=*/" const &&",
},
{ "_ZTV11ImageLoader",
{ /*.BasenameRange=*/{0, 0}, /*.ScopeRange=*/{0, 0}, /*.ArgumentsRange=*/{ 0, 0 },
/*.QualifiersRange=*/{0, 0} },
/*.QualifiersRange=*/{0, 0}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
/*.basename=*/"",
/*.scope=*/"",
/*.qualifiers=*/"",
/*.valid_basename=*/false
},
{ "___ZNK5dyld313MachOAnalyzer18forEachInitializerER11DiagnosticsRKNS0_15VMAddrConverterEU13block_pointerFvjEPKv_block_invoke.204",
{ /*.BasenameRange=*/{55, 73}, /*.ScopeRange=*/{33, 55}, /*.ArgumentsRange=*/{ 73, 181 },
/*.QualifiersRange=*/{181, 187}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
/*.basename=*/"forEachInitializer",
/*.scope=*/"dyld3::MachOAnalyzer::",
/*.qualifiers=*/" const",
},
{ "_ZZN5dyld45startEPNS_10KernelArgsEPvS2_ENK3$_1clEv",
{ /*.BasenameRange=*/{53, 63}, /*.ScopeRange=*/{0, 53}, /*.ArgumentsRange=*/{ 63, 65 },
/*.QualifiersRange=*/{65, 71}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
/*.basename=*/"operator()",
/*.scope=*/"dyld4::start(dyld4::KernelArgs*, void*, void*)::$_1::",
/*.qualifiers=*/" const",
},
{ "_ZZNK5dyld46Loader38runInitializersBottomUpPlusUpwardLinksERNS_12RuntimeStateEENK3$_0clEv",
{ /*.BasenameRange=*/{88, 98}, /*.ScopeRange=*/{0, 88}, /*.ArgumentsRange=*/{ 98, 100 },
/*.QualifiersRange=*/{100, 106}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
/*.basename=*/"operator()",
/*.scope=*/"dyld4::Loader::runInitializersBottomUpPlusUpwardLinks(dyld4::RuntimeState&) const::$_0::",
/*.qualifiers=*/" const",
},
{ "_ZZNK5dyld46Loader38runInitializersBottomUpPlusUpwardLinksERNS_12RuntimeStateEENK3$_0clEv.cold",
{ /*.BasenameRange=*/{88, 98}, /*.ScopeRange=*/{0, 88}, /*.ArgumentsRange=*/{ 98, 100 },
/*.QualifiersRange=*/{100, 106}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
/*.basename=*/"operator()",
/*.scope=*/"dyld4::Loader::runInitializersBottomUpPlusUpwardLinks(dyld4::RuntimeState&) const::$_0::",
/*.qualifiers=*/" const",
}
// clang-format on
};