blob: 3ea7589d8e4a8c2965b1b3b243df13bd948febb3 [file] [log] [blame]
//===-- 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 <algorithm>
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<uint64_t> 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<uint64_t> 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;
}