Skip to content

Commit 570732b

Browse files
committed
[LLDB] Add type summaries for MSVC STL strings
1 parent 1f10c6a commit 570732b

File tree

18 files changed

+597
-31
lines changed

18 files changed

+597
-31
lines changed

lldb/include/lldb/DataFormatters/StringPrinter.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,21 @@ class StringPrinter {
152152
template <StringElementType element_type>
153153
static bool
154154
ReadBufferAndDumpToStream(const ReadBufferAndDumpToStreamOptions &options);
155+
156+
template <StringElementType element_type>
157+
static constexpr uint64_t ElementByteSize() {
158+
switch (element_type) {
159+
case StringElementType::ASCII:
160+
case StringElementType::UTF8:
161+
return 1;
162+
case StringElementType::UTF16:
163+
return 2;
164+
case StringElementType::UTF32:
165+
return 3;
166+
default:
167+
return 0;
168+
}
169+
}
155170
};
156171

157172
} // namespace formatters

lldb/packages/Python/lldbsuite/test/configuration.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@
134134
libcxx_include_target_dir = None
135135
libcxx_library_dir = None
136136

137+
target_triple = None
138+
137139
# A plugin whose tests will be enabled, like intel-pt.
138140
enabled_plugins = []
139141

lldb/packages/Python/lldbsuite/test/dotest.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,8 @@ def parseOptionsAndInitTestdirs():
299299
configuration.libcxx_library_dir = args.libcxx_library_dir
300300
configuration.cmake_build_type = args.cmake_build_type.lower()
301301

302+
configuration.target_triple = args.target_triple
303+
302304
if args.channels:
303305
lldbtest_config.channels = args.channels
304306

@@ -831,6 +833,26 @@ def checkLibstdcxxSupport():
831833
configuration.skip_categories.append("libstdcxx")
832834

833835

836+
def canRunMsvcStlTests():
837+
if "windows-msvc" in configuration.target_triple:
838+
return True, "MSVC STL is present on *windows-msvc*"
839+
return (
840+
False,
841+
f"Don't know how to build with MSVC's STL on {configuration.target_triple}",
842+
)
843+
844+
845+
def checkMsvcStlSupport():
846+
result, reason = canRunMsvcStlTests()
847+
if result:
848+
return # msvcstl supported
849+
if "msvcstl" in configuration.categories_list:
850+
return # msvcstl category explicitly requested, let it run.
851+
if configuration.verbose:
852+
print(f"msvcstl tests will not be run because: {reason}")
853+
configuration.skip_categories.append("msvcstl")
854+
855+
834856
def canRunWatchpointTests():
835857
from lldbsuite.test import lldbplatformutil
836858

@@ -1044,6 +1066,7 @@ def run_suite():
10441066

10451067
checkLibcxxSupport()
10461068
checkLibstdcxxSupport()
1069+
checkMsvcStlSupport()
10471070
checkWatchpointSupport()
10481071
checkDebugInfoSupport()
10491072
checkDebugServerSupport()

lldb/packages/Python/lldbsuite/test/dotest_args.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@ def create_parser():
116116
"The location of llvm tools used for testing (yaml2obj, FileCheck, etc.)."
117117
),
118118
)
119+
group.add_argument(
120+
"--target-triple",
121+
help=textwrap.dedent(
122+
"The target triple the tests will run on (e.g. x86_64-pc-windows-msvc)."
123+
),
124+
)
119125

120126
# Test filtering options
121127
group = parser.add_argument_group("Test filtering options")

lldb/packages/Python/lldbsuite/test/test_categories.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
"lldb-server": "Tests related to lldb-server",
3434
"lldb-dap": "Tests for the Debug Adapter Protocol with lldb-dap",
3535
"llgs": "Tests for the gdb-server functionality of lldb-server",
36+
"msvcstl": "Test for MSVC STL data formatters",
3637
"pexpect": "Tests requiring the pexpect library to be available",
3738
"objc": "Tests related to the Objective-C programming language support",
3839
"pyapi": "Tests related to the Python API",

lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN
3232
LibStdcpp.cpp
3333
LibStdcppTuple.cpp
3434
LibStdcppUniquePointer.cpp
35+
MsvcStl.cpp
3536
MSVCUndecoratedNameParser.cpp
3637

3738
LINK_COMPONENTS

lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp

Lines changed: 108 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include "LibCxxVariant.h"
4747
#include "LibStdcpp.h"
4848
#include "MSVCUndecoratedNameParser.h"
49+
#include "MsvcStl.h"
4950
#include "lldb/lldb-enumerations.h"
5051

5152
using namespace lldb;
@@ -1372,6 +1373,36 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
13721373
"${var.__y_} ${var.__m_} ${var.__wdl_}")));
13731374
}
13741375

1376+
static void RegisterStdStringSummaryProvider(
1377+
const lldb::TypeCategoryImplSP &category_sp, llvm::StringRef string_ty,
1378+
llvm::StringRef char_ty, lldb::TypeSummaryImplSP summary_sp) {
1379+
auto makeSpecifier = [](llvm::StringRef name) {
1380+
return std::make_shared<lldb_private::TypeNameSpecifierImpl>(
1381+
name, eFormatterMatchExact);
1382+
};
1383+
1384+
category_sp->AddTypeSummary(makeSpecifier(string_ty), summary_sp);
1385+
1386+
// std::basic_string<char>
1387+
category_sp->AddTypeSummary(
1388+
makeSpecifier((llvm::Twine("std::basic_string<") + char_ty + ">").str()),
1389+
summary_sp);
1390+
// std::basic_string<char,std::char_traits<char>,std::allocator<char> >
1391+
category_sp->AddTypeSummary(
1392+
makeSpecifier((llvm::Twine("std::basic_string<") + char_ty +
1393+
",std::char_traits<" + char_ty + ">,std::allocator<" +
1394+
char_ty + "> >")
1395+
.str()),
1396+
summary_sp);
1397+
// std::basic_string<char, std::char_traits<char>, std::allocator<char> >
1398+
category_sp->AddTypeSummary(
1399+
makeSpecifier((llvm::Twine("std::basic_string<") + char_ty +
1400+
", std::char_traits<" + char_ty + ">, std::allocator<" +
1401+
char_ty + "> >")
1402+
.str()),
1403+
summary_sp);
1404+
}
1405+
13751406
static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
13761407
if (!cpp_category_sp)
13771408
return;
@@ -1385,27 +1416,13 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
13851416
.SetShowMembersOneLiner(false)
13861417
.SetHideItemNames(false);
13871418

1388-
lldb::TypeSummaryImplSP std_string_summary_sp(
1389-
new StringSummaryFormat(stl_summary_flags, "${var._M_dataplus._M_p}"));
1390-
13911419
lldb::TypeSummaryImplSP cxx11_string_summary_sp(new CXXFunctionSummaryFormat(
13921420
stl_summary_flags, LibStdcppStringSummaryProvider,
13931421
"libstdc++ c++11 std::string summary provider"));
13941422
lldb::TypeSummaryImplSP cxx11_wstring_summary_sp(new CXXFunctionSummaryFormat(
13951423
stl_summary_flags, LibStdcppWStringSummaryProvider,
13961424
"libstdc++ c++11 std::wstring summary provider"));
13971425

1398-
cpp_category_sp->AddTypeSummary("std::string", eFormatterMatchExact,
1399-
std_string_summary_sp);
1400-
cpp_category_sp->AddTypeSummary("std::basic_string<char>",
1401-
eFormatterMatchExact, std_string_summary_sp);
1402-
cpp_category_sp->AddTypeSummary(
1403-
"std::basic_string<char,std::char_traits<char>,std::allocator<char> >",
1404-
eFormatterMatchExact, std_string_summary_sp);
1405-
cpp_category_sp->AddTypeSummary(
1406-
"std::basic_string<char, std::char_traits<char>, std::allocator<char> >",
1407-
eFormatterMatchExact, std_string_summary_sp);
1408-
14091426
cpp_category_sp->AddTypeSummary("std::__cxx11::string", eFormatterMatchExact,
14101427
cxx11_string_summary_sp);
14111428
cpp_category_sp->AddTypeSummary(
@@ -1418,23 +1435,6 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
14181435
eFormatterMatchExact,
14191436
cxx11_string_summary_sp);
14201437

1421-
// making sure we force-pick the summary for printing wstring (_M_p is a
1422-
// wchar_t*)
1423-
lldb::TypeSummaryImplSP std_wstring_summary_sp(
1424-
new StringSummaryFormat(stl_summary_flags, "${var._M_dataplus._M_p%S}"));
1425-
1426-
cpp_category_sp->AddTypeSummary("std::wstring", eFormatterMatchExact,
1427-
std_wstring_summary_sp);
1428-
cpp_category_sp->AddTypeSummary("std::basic_string<wchar_t>",
1429-
eFormatterMatchExact, std_wstring_summary_sp);
1430-
cpp_category_sp->AddTypeSummary("std::basic_string<wchar_t,std::char_traits<"
1431-
"wchar_t>,std::allocator<wchar_t> >",
1432-
eFormatterMatchExact, std_wstring_summary_sp);
1433-
cpp_category_sp->AddTypeSummary(
1434-
"std::basic_string<wchar_t, std::char_traits<wchar_t>, "
1435-
"std::allocator<wchar_t> >",
1436-
eFormatterMatchExact, std_wstring_summary_sp);
1437-
14381438
cpp_category_sp->AddTypeSummary("std::__cxx11::wstring", eFormatterMatchExact,
14391439
cxx11_wstring_summary_sp);
14401440
cpp_category_sp->AddTypeSummary(
@@ -1629,6 +1629,81 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
16291629
"^std::optional<.+>(( )?&)?$", stl_summary_flags, true);
16301630
}
16311631

1632+
static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
1633+
if (!cpp_category_sp)
1634+
return;
1635+
1636+
TypeSummaryImpl::Flags stl_summary_flags;
1637+
stl_summary_flags.SetCascades(true)
1638+
.SetSkipPointers(false)
1639+
.SetSkipReferences(false)
1640+
.SetDontShowChildren(true)
1641+
.SetDontShowValue(false)
1642+
.SetShowMembersOneLiner(false)
1643+
.SetHideItemNames(false);
1644+
using StringElementType = StringPrinter::StringElementType;
1645+
1646+
RegisterStdStringSummaryProvider(
1647+
cpp_category_sp, "std::string", "char",
1648+
std::make_shared<CXXFunctionSummaryFormat>(
1649+
stl_summary_flags,
1650+
[](ValueObject &valobj, Stream &stream,
1651+
const TypeSummaryOptions &options) {
1652+
if (IsMsvcStdStringType(valobj))
1653+
return MsvcStlStringSummaryProvider<StringElementType::ASCII>(
1654+
valobj, stream, options);
1655+
return LibStdcppPre11StringSummaryProvider(valobj, stream, options);
1656+
},
1657+
"MSVC STL/libstdc++ std::string summary provider"));
1658+
RegisterStdStringSummaryProvider(
1659+
cpp_category_sp, "std::wstring", "wchar_t",
1660+
std::make_shared<CXXFunctionSummaryFormat>(
1661+
stl_summary_flags,
1662+
[](ValueObject &valobj, Stream &stream,
1663+
const TypeSummaryOptions &options) {
1664+
if (IsMsvcStdStringType(valobj))
1665+
return MsvcStlWStringSummaryProvider(valobj, stream, options);
1666+
return LibStdcppPre11WStringSummaryProvider(valobj, stream,
1667+
options);
1668+
},
1669+
"MSVC STL/libstdc++ std::wstring summary provider"));
1670+
}
1671+
1672+
static void LoadMsvcStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
1673+
if (!cpp_category_sp)
1674+
return;
1675+
1676+
TypeSummaryImpl::Flags stl_summary_flags;
1677+
stl_summary_flags.SetCascades(true)
1678+
.SetSkipPointers(false)
1679+
.SetSkipReferences(false)
1680+
.SetDontShowChildren(true)
1681+
.SetDontShowValue(false)
1682+
.SetShowMembersOneLiner(false)
1683+
.SetHideItemNames(false);
1684+
1685+
using StringElementType = StringPrinter::StringElementType;
1686+
1687+
RegisterStdStringSummaryProvider(
1688+
cpp_category_sp, "std::u8string", "char8_t",
1689+
std::make_shared<CXXFunctionSummaryFormat>(
1690+
stl_summary_flags,
1691+
MsvcStlStringSummaryProvider<StringElementType::UTF8>,
1692+
"MSVC STL std::u8string summary provider"));
1693+
RegisterStdStringSummaryProvider(
1694+
cpp_category_sp, "std::u16string", "char16_t",
1695+
std::make_shared<CXXFunctionSummaryFormat>(
1696+
stl_summary_flags,
1697+
MsvcStlStringSummaryProvider<StringElementType::UTF16>,
1698+
"MSVC STL std::u16string summary provider"));
1699+
RegisterStdStringSummaryProvider(
1700+
cpp_category_sp, "std::u32string", "char32_t",
1701+
std::make_shared<CXXFunctionSummaryFormat>(
1702+
stl_summary_flags,
1703+
MsvcStlStringSummaryProvider<StringElementType::UTF32>,
1704+
"MSVC STL std::u32string summary provider"));
1705+
}
1706+
16321707
static void LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
16331708
if (!cpp_category_sp)
16341709
return;
@@ -1743,6 +1818,8 @@ lldb::TypeCategoryImplSP CPlusPlusLanguage::GetFormatters() {
17431818
// LLDB prioritizes the last loaded matching formatter.
17441819
LoadLibCxxFormatters(g_category);
17451820
LoadLibStdcppFormatters(g_category);
1821+
LoadMsvcStlFormatters(g_category);
1822+
LoadCommonStlFormatters(g_category);
17461823
LoadSystemFormatters(g_category);
17471824
}
17481825
});

lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "LibStdcpp.h"
10+
#include "CxxStringTypes.h"
1011
#include "LibCxx.h"
1112

1213
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
@@ -237,6 +238,43 @@ VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName(ConstString name) {
237238
name.AsCString());
238239
}
239240

241+
bool lldb_private::formatters::LibStdcppPre11StringSummaryProvider(
242+
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
243+
ValueObjectSP dataplus = valobj.GetChildMemberWithName("_M_dataplus");
244+
if (!dataplus)
245+
return false;
246+
ValueObjectSP ptr = dataplus->GetChildMemberWithName("_M_p");
247+
if (!ptr)
248+
return false;
249+
250+
Address valobj_addr = valobj.GetPointerValue().address;
251+
if (!valobj_addr.IsValid())
252+
return false;
253+
254+
StringPrinter::ReadStringAndDumpToStreamOptions printer_opts(valobj);
255+
printer_opts.SetLocation(valobj_addr);
256+
printer_opts.SetTargetSP(valobj.GetTargetSP());
257+
printer_opts.SetStream(&stream);
258+
259+
if (!StringPrinter::ReadStringAndDumpToStream<
260+
StringPrinter::StringElementType::ASCII>(printer_opts))
261+
stream.Printf("Summary Unavailable");
262+
263+
return true;
264+
}
265+
266+
bool lldb_private::formatters::LibStdcppPre11WStringSummaryProvider(
267+
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
268+
ValueObjectSP dataplus = valobj.GetChildMemberWithName("_M_dataplus");
269+
if (!dataplus)
270+
return false;
271+
ValueObjectSP ptr = dataplus->GetChildMemberWithName("_M_p");
272+
if (!ptr)
273+
return false;
274+
275+
return WCharStringSummaryProvider(*ptr, stream, options);
276+
}
277+
240278
bool lldb_private::formatters::LibStdcppStringSummaryProvider(
241279
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
242280
const bool scalar_is_load_addr = true;

lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@
1616

1717
namespace lldb_private {
1818
namespace formatters {
19+
bool LibStdcppPre11StringSummaryProvider(
20+
ValueObject &valobj, Stream &stream,
21+
const TypeSummaryOptions &options); // libstdc++ pre-c++11 std::string
22+
23+
bool LibStdcppPre11WStringSummaryProvider(
24+
ValueObject &valobj, Stream &stream,
25+
const TypeSummaryOptions &options); // libstdc++ pre-c++11 std::wstring
26+
1927
bool LibStdcppStringSummaryProvider(
2028
ValueObject &valobj, Stream &stream,
2129
const TypeSummaryOptions &options); // libcstdc++ c++11 std::string

0 commit comments

Comments
 (0)