//===-- MsvcStl.cpp -------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "MsvcStl.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/FormatEntity.h" #include "lldb/DataFormatters/StringPrinter.h" #include "lldb/DataFormatters/TypeSummary.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/Stream.h" #include "lldb/ValueObject/ValueObject.h" #include "Plugins/Language/CPlusPlus/CxxStringTypes.h" #include "lldb/lldb-forward.h" #include #include using namespace lldb; using namespace lldb_private; using namespace lldb_private::formatters; using StringElementType = StringPrinter::StringElementType; template static constexpr uint64_t StringElementByteSize() { switch (element_type) { case StringElementType::ASCII: case StringElementType::UTF8: return 1; case StringElementType::UTF16: return 2; case StringElementType::UTF32: return 3; } return 0; } static ValueObjectSP ExtractMsvcStlStringData(ValueObject &valobj) { return valobj.GetChildAtNamePath({"_Mypair", "_Myval2"}); } /// Determine the size in bytes of \p valobj (a MSVC STL std::string object) and /// extract its data payload. Return the size + payload pair. static std::optional> ExtractMsvcStlStringInfo(ValueObject &valobj, uint64_t element_size) { ValueObjectSP valobj_pair_sp = ExtractMsvcStlStringData(valobj); if (!valobj_pair_sp || !valobj_pair_sp->GetError().Success()) return {}; ValueObjectSP size_sp = valobj_pair_sp->GetChildMemberWithName("_Mysize"); ValueObjectSP capacity_sp = valobj_pair_sp->GetChildMemberWithName("_Myres"); ValueObjectSP bx_sp = valobj_pair_sp->GetChildMemberWithName("_Bx"); if (!size_sp || !capacity_sp || !bx_sp) return {}; bool success = false; uint64_t size = size_sp->GetValueAsUnsigned(0, &success); if (!success) return {}; uint64_t capacity = capacity_sp->GetValueAsUnsigned(0, &success); if (!success) return {}; size_t bufSize = std::max(16 / element_size, 1); bool isShortString = capacity < bufSize; if (isShortString) { ValueObjectSP buf_sp = bx_sp->GetChildMemberWithName("_Buf"); if (buf_sp) return std::make_pair(size, buf_sp); return {}; } ValueObjectSP ptr_sp = bx_sp->GetChildMemberWithName("_Ptr"); if (ptr_sp) return std::make_pair(size, ptr_sp); return {}; } template static bool MsvcStlStringSummaryProviderImpl(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options, std::string prefix_token) { auto string_info = ExtractMsvcStlStringInfo(valobj, StringElementByteSize()); if (!string_info) return false; auto [size, location_sp] = *string_info; return StringBufferSummaryProvider( stream, summary_options, location_sp, size, prefix_token); } template static bool formatStringImpl(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options, std::string prefix_token) { StreamString scratch_stream; const bool success = MsvcStlStringSummaryProviderImpl( valobj, scratch_stream, summary_options, prefix_token); if (success) stream << scratch_stream.GetData(); else stream << "Summary Unavailable"; return true; } template static bool formatStringViewImpl(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options, std::string prefix_token) { auto data_sp = valobj.GetChildMemberWithName("_Mydata"); auto size_sp = valobj.GetChildMemberWithName("_Mysize"); if (!data_sp || !size_sp) return false; bool success = false; uint64_t size = size_sp->GetValueAsUnsigned(0, &success); if (!success) { stream << "Summary Unavailable"; return true; } StreamString scratch_stream; success = StringBufferSummaryProvider( scratch_stream, summary_options, data_sp, size, prefix_token); if (success) stream << scratch_stream.GetData(); else stream << "Summary Unavailable"; return true; } bool lldb_private::formatters::IsMsvcStlStringType(ValueObject &valobj) { std::vector indexes; return valobj.GetCompilerType().GetIndexOfChildMemberWithName("_Mypair", true, indexes) > 0; } bool lldb_private::formatters::MsvcStlWStringSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options) { return formatStringImpl(valobj, stream, summary_options, "L"); } template <> bool lldb_private::formatters::MsvcStlStringSummaryProvider< StringElementType::ASCII>(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options) { return MsvcStlStringSummaryProviderImpl( valobj, stream, summary_options, ""); } template <> bool lldb_private::formatters::MsvcStlStringSummaryProvider< StringElementType::UTF8>(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options) { return MsvcStlStringSummaryProviderImpl( valobj, stream, summary_options, "u8"); } template <> bool lldb_private::formatters::MsvcStlStringSummaryProvider< StringElementType::UTF16>(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options) { return MsvcStlStringSummaryProviderImpl( valobj, stream, summary_options, "u"); } template <> bool lldb_private::formatters::MsvcStlStringSummaryProvider< StringElementType::UTF32>(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options) { return MsvcStlStringSummaryProviderImpl( valobj, stream, summary_options, "U"); } bool lldb_private::formatters::MsvcStlWStringViewSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options) { return formatStringViewImpl(valobj, stream, summary_options, "L"); } template <> bool lldb_private::formatters::MsvcStlStringViewSummaryProvider< StringElementType::ASCII>(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options) { return formatStringViewImpl(valobj, stream, summary_options, ""); } template <> bool lldb_private::formatters::MsvcStlStringViewSummaryProvider< StringElementType::UTF8>(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options) { return formatStringViewImpl(valobj, stream, summary_options, "u8"); } template <> bool lldb_private::formatters::MsvcStlStringViewSummaryProvider< StringElementType::UTF16>(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options) { return formatStringViewImpl(valobj, stream, summary_options, "u"); } template <> bool lldb_private::formatters::MsvcStlStringViewSummaryProvider< StringElementType::UTF32>(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options) { return formatStringViewImpl(valobj, stream, summary_options, "U"); }