//===-- CxxStringTypes.cpp --------------------------------------*- C++ -*-===// // // 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 "CxxStringTypes.h" #include "llvm/Support/ConvertUTF.h" #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/DataFormatters/FormattersHelpers.h" #include "lldb/DataFormatters/StringPrinter.h" #include "lldb/DataFormatters/TypeSummary.h" #include "lldb/Host/Time.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Target/ProcessStructReader.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/Endian.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/Stream.h" #include using namespace lldb; using namespace lldb_private; using namespace lldb_private::formatters; bool lldb_private::formatters::Char8StringSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) return false; lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj); if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS) return false; StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); options.SetLocation(valobj_addr); options.SetProcessSP(process_sp); options.SetStream(&stream); options.SetPrefixToken("u8"); if (!StringPrinter::ReadStringAndDumpToStream< StringPrinter::StringElementType::UTF8>(options)) { stream.Printf("Summary Unavailable"); return true; } return true; } bool lldb_private::formatters::Char16StringSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) return false; lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj); if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS) return false; StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); options.SetLocation(valobj_addr); options.SetProcessSP(process_sp); options.SetStream(&stream); options.SetPrefixToken("u"); if (!StringPrinter::ReadStringAndDumpToStream< StringPrinter::StringElementType::UTF16>(options)) { stream.Printf("Summary Unavailable"); return true; } return true; } bool lldb_private::formatters::Char32StringSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) return false; lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj); if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS) return false; StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); options.SetLocation(valobj_addr); options.SetProcessSP(process_sp); options.SetStream(&stream); options.SetPrefixToken("U"); if (!StringPrinter::ReadStringAndDumpToStream< StringPrinter::StringElementType::UTF32>(options)) { stream.Printf("Summary Unavailable"); return true; } return true; } bool lldb_private::formatters::WCharStringSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) return false; lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj); if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS) return false; // Get a wchar_t basic type from the current type system CompilerType wchar_compiler_type = valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar); if (!wchar_compiler_type) return false; // Safe to pass nullptr for exe_scope here. llvm::Optional size = wchar_compiler_type.GetBitSize(nullptr); if (!size) return false; const uint32_t wchar_size = *size; StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); options.SetLocation(valobj_addr); options.SetProcessSP(process_sp); options.SetStream(&stream); options.SetPrefixToken("L"); switch (wchar_size) { case 8: return StringPrinter::ReadStringAndDumpToStream< StringPrinter::StringElementType::UTF8>(options); case 16: return StringPrinter::ReadStringAndDumpToStream< StringPrinter::StringElementType::UTF16>(options); case 32: return StringPrinter::ReadStringAndDumpToStream< StringPrinter::StringElementType::UTF32>(options); default: stream.Printf("size for wchar_t is not valid"); return true; } return true; } bool lldb_private::formatters::Char8SummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { DataExtractor data; Status error; valobj.GetData(data, error); if (error.Fail()) return false; std::string value; valobj.GetValueAsCString(lldb::eFormatUnicode8, value); if (!value.empty()) stream.Printf("%s ", value.c_str()); StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); options.SetData(data); options.SetStream(&stream); options.SetPrefixToken("u8"); options.SetQuote('\''); options.SetSourceSize(1); options.SetBinaryZeroIsTerminator(false); return StringPrinter::ReadBufferAndDumpToStream< StringPrinter::StringElementType::UTF8>(options); } bool lldb_private::formatters::Char16SummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { DataExtractor data; Status error; valobj.GetData(data, error); if (error.Fail()) return false; std::string value; valobj.GetValueAsCString(lldb::eFormatUnicode16, value); if (!value.empty()) stream.Printf("%s ", value.c_str()); StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); options.SetData(data); options.SetStream(&stream); options.SetPrefixToken("u"); options.SetQuote('\''); options.SetSourceSize(1); options.SetBinaryZeroIsTerminator(false); return StringPrinter::ReadBufferAndDumpToStream< StringPrinter::StringElementType::UTF16>(options); } bool lldb_private::formatters::Char32SummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { DataExtractor data; Status error; valobj.GetData(data, error); if (error.Fail()) return false; std::string value; valobj.GetValueAsCString(lldb::eFormatUnicode32, value); if (!value.empty()) stream.Printf("%s ", value.c_str()); StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); options.SetData(data); options.SetStream(&stream); options.SetPrefixToken("U"); options.SetQuote('\''); options.SetSourceSize(1); options.SetBinaryZeroIsTerminator(false); return StringPrinter::ReadBufferAndDumpToStream< StringPrinter::StringElementType::UTF32>(options); } bool lldb_private::formatters::WCharSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { DataExtractor data; Status error; valobj.GetData(data, error); if (error.Fail()) return false; // Get a wchar_t basic type from the current type system CompilerType wchar_compiler_type = valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar); if (!wchar_compiler_type) return false; // Safe to pass nullptr for exe_scope here. llvm::Optional size = wchar_compiler_type.GetBitSize(nullptr); if (!size) return false; const uint32_t wchar_size = *size; StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); options.SetData(data); options.SetStream(&stream); options.SetPrefixToken("L"); options.SetQuote('\''); options.SetSourceSize(1); options.SetBinaryZeroIsTerminator(false); switch (wchar_size) { case 8: return StringPrinter::ReadBufferAndDumpToStream< StringPrinter::StringElementType::UTF8>(options); case 16: return StringPrinter::ReadBufferAndDumpToStream< StringPrinter::StringElementType::UTF16>(options); case 32: return StringPrinter::ReadBufferAndDumpToStream< StringPrinter::StringElementType::UTF32>(options); default: stream.Printf("size for wchar_t is not valid"); return true; } return true; }