[lldb][NFC] Fix all formatting errors in .cpp file headers
Summary:
A *.cpp file header in LLDB (and in LLDB) should like this:
```
//===-- TestUtilities.cpp -------------------------------------------------===//
```
However in LLDB most of our source files have arbitrary changes to this format and
these changes are spreading through LLDB as folks usually just use the existing
source files as templates for their new files (most notably the unnecessary
editor language indicator `-*- C++ -*-` is spreading and in every review
someone is pointing out that this is wrong, resulting in people pointing out that this
is done in the same way in other files).
This patch removes most of these inconsistencies including the editor language indicators,
all the different missing/additional '-' characters, files that center the file name, missing
trailing `===//` (mostly caused by clang-format breaking the line).
Reviewers: aprantl, espindola, jfb, shafik, JDevlieghere
Reviewed By: JDevlieghere
Subscribers: dexonsmith, wuzish, emaste, sdardis, nemanjai, kbarton, MaskRay, atanasyan, arphaman, jfb, abidh, jsji, JDevlieghere, usaxena95, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D73258
2020-01-24 08:23:27 +01:00
|
|
|
//===-- LibCxx.cpp --------------------------------------------------------===//
|
2013-02-21 19:57:10 +00:00
|
|
|
//
|
2019-01-19 08:50:56 +00:00
|
|
|
// 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
|
2013-02-21 19:57:10 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2015-09-04 21:01:18 +00:00
|
|
|
#include "LibCxx.h"
|
2013-02-21 19:57:10 +00:00
|
|
|
|
2013-05-06 18:55:52 +00:00
|
|
|
#include "lldb/Core/Debugger.h"
|
2015-02-04 22:00:53 +00:00
|
|
|
#include "lldb/Core/FormatEntity.h"
|
2013-02-21 19:57:10 +00:00
|
|
|
#include "lldb/Core/ValueObject.h"
|
|
|
|
#include "lldb/Core/ValueObjectConstResult.h"
|
2015-09-04 00:33:51 +00:00
|
|
|
#include "lldb/DataFormatters/FormattersHelpers.h"
|
|
|
|
#include "lldb/DataFormatters/StringPrinter.h"
|
|
|
|
#include "lldb/DataFormatters/TypeSummary.h"
|
|
|
|
#include "lldb/DataFormatters/VectorIterator.h"
|
2017-02-14 19:06:07 +00:00
|
|
|
#include "lldb/Target/ProcessStructReader.h"
|
2018-08-23 17:02:39 +00:00
|
|
|
#include "lldb/Target/SectionLoadList.h"
|
2013-02-21 19:57:10 +00:00
|
|
|
#include "lldb/Target/Target.h"
|
2022-01-07 11:38:47 -08:00
|
|
|
#include "lldb/Utility/ConstString.h"
|
2017-03-04 01:30:05 +00:00
|
|
|
#include "lldb/Utility/DataBufferHeap.h"
|
2017-02-14 19:06:07 +00:00
|
|
|
#include "lldb/Utility/Endian.h"
|
2017-05-12 04:51:55 +00:00
|
|
|
#include "lldb/Utility/Status.h"
|
2017-02-02 21:39:50 +00:00
|
|
|
#include "lldb/Utility/Stream.h"
|
2013-02-21 19:57:10 +00:00
|
|
|
|
2019-07-12 20:09:32 +00:00
|
|
|
#include "Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h"
|
[lldb] Move clang-based files out of Symbol
Summary:
This change represents the move of ClangASTImporter, ClangASTMetadata,
ClangExternalASTSourceCallbacks, ClangUtil, CxxModuleHandler, and
TypeSystemClang from lldbSource to lldbPluginExpressionParserClang.h
This explicitly removes knowledge of clang internals from lldbSymbol,
moving towards a more generic core implementation of lldb.
Reviewers: JDevlieghere, davide, aprantl, teemperor, clayborg, labath, jingham, shafik
Subscribers: emaste, mgorny, arphaman, jfb, usaxena95, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D73661
2020-01-29 11:59:28 -08:00
|
|
|
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
|
2022-07-08 10:47:04 +01:00
|
|
|
#include "lldb/lldb-enumerations.h"
|
2022-01-07 11:38:47 -08:00
|
|
|
#include <tuple>
|
2019-07-12 20:09:32 +00:00
|
|
|
|
2013-02-21 19:57:10 +00:00
|
|
|
using namespace lldb;
|
|
|
|
using namespace lldb_private;
|
|
|
|
using namespace lldb_private::formatters;
|
|
|
|
|
2022-09-09 15:58:14 -07:00
|
|
|
lldb::ValueObjectSP lldb_private::formatters::GetChildMemberWithName(
|
|
|
|
ValueObject &obj, llvm::ArrayRef<ConstString> alternative_names) {
|
|
|
|
for (ConstString name : alternative_names) {
|
|
|
|
lldb::ValueObjectSP child_sp = obj.GetChildMemberWithName(name, true);
|
|
|
|
|
|
|
|
if (child_sp)
|
|
|
|
return child_sp;
|
|
|
|
}
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2018-08-15 22:48:48 +00:00
|
|
|
bool lldb_private::formatters::LibcxxOptionalSummaryProvider(
|
|
|
|
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
|
|
|
|
ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
|
|
|
|
if (!valobj_sp)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// An optional either contains a value or not, the member __engaged_ is
|
|
|
|
// a bool flag, it is true if the optional has a value and false otherwise.
|
|
|
|
ValueObjectSP engaged_sp(
|
|
|
|
valobj_sp->GetChildMemberWithName(ConstString("__engaged_"), true));
|
|
|
|
|
|
|
|
if (!engaged_sp)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
llvm::StringRef engaged_as_cstring(
|
|
|
|
engaged_sp->GetValueAsUnsigned(0) == 1 ? "true" : "false");
|
|
|
|
|
|
|
|
stream.Printf(" Has Value=%s ", engaged_as_cstring.data());
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-08-23 17:02:39 +00:00
|
|
|
bool lldb_private::formatters::LibcxxFunctionSummaryProvider(
|
|
|
|
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
|
|
|
|
|
|
|
|
ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
|
|
|
|
|
|
|
|
if (!valobj_sp)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
ExecutionContext exe_ctx(valobj_sp->GetExecutionContextRef());
|
|
|
|
Process *process = exe_ctx.GetProcessPtr();
|
|
|
|
|
|
|
|
if (process == nullptr)
|
|
|
|
return false;
|
|
|
|
|
2019-06-10 21:04:31 +00:00
|
|
|
CPPLanguageRuntime *cpp_runtime = CPPLanguageRuntime::Get(*process);
|
2018-08-23 17:02:39 +00:00
|
|
|
|
2018-09-11 20:58:28 +00:00
|
|
|
if (!cpp_runtime)
|
2018-08-23 17:02:39 +00:00
|
|
|
return false;
|
|
|
|
|
2018-09-11 20:58:28 +00:00
|
|
|
CPPLanguageRuntime::LibCppStdFunctionCallableInfo callable_info =
|
|
|
|
cpp_runtime->FindLibCppStdFunctionCallableInfo(valobj_sp);
|
2018-08-23 17:02:39 +00:00
|
|
|
|
2018-09-11 20:58:28 +00:00
|
|
|
switch (callable_info.callable_case) {
|
|
|
|
case CPPLanguageRuntime::LibCppStdFunctionCallableCase::Invalid:
|
2022-02-16 11:51:50 -08:00
|
|
|
stream.Printf(" __f_ = %" PRIu64, callable_info.member_f_pointer_value);
|
2018-08-23 17:02:39 +00:00
|
|
|
return false;
|
2018-09-11 20:58:28 +00:00
|
|
|
break;
|
|
|
|
case CPPLanguageRuntime::LibCppStdFunctionCallableCase::Lambda:
|
|
|
|
stream.Printf(
|
|
|
|
" Lambda in File %s at Line %u",
|
|
|
|
callable_info.callable_line_entry.file.GetFilename().GetCString(),
|
|
|
|
callable_info.callable_line_entry.line);
|
|
|
|
break;
|
|
|
|
case CPPLanguageRuntime::LibCppStdFunctionCallableCase::CallableObject:
|
|
|
|
stream.Printf(
|
|
|
|
" Function in File %s at Line %u",
|
|
|
|
callable_info.callable_line_entry.file.GetFilename().GetCString(),
|
|
|
|
callable_info.callable_line_entry.line);
|
|
|
|
break;
|
|
|
|
case CPPLanguageRuntime::LibCppStdFunctionCallableCase::FreeOrMemberFunction:
|
|
|
|
stream.Printf(" Function = %s ",
|
|
|
|
callable_info.callable_symbol.GetName().GetCString());
|
|
|
|
break;
|
2018-08-23 17:02:39 +00:00
|
|
|
}
|
|
|
|
|
2018-09-11 20:58:28 +00:00
|
|
|
return true;
|
2018-08-23 17:02:39 +00:00
|
|
|
}
|
|
|
|
|
2014-11-06 21:55:30 +00:00
|
|
|
bool lldb_private::formatters::LibcxxSmartPointerSummaryProvider(
|
|
|
|
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
|
2014-01-08 01:36:59 +00:00
|
|
|
ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
|
|
|
|
if (!valobj_sp)
|
|
|
|
return false;
|
|
|
|
ValueObjectSP ptr_sp(
|
|
|
|
valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true));
|
|
|
|
ValueObjectSP count_sp(valobj_sp->GetChildAtNamePath(
|
|
|
|
{ConstString("__cntrl_"), ConstString("__shared_owners_")}));
|
|
|
|
ValueObjectSP weakcount_sp(valobj_sp->GetChildAtNamePath(
|
|
|
|
{ConstString("__cntrl_"), ConstString("__shared_weak_owners_")}));
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2014-01-08 01:36:59 +00:00
|
|
|
if (!ptr_sp)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (ptr_sp->GetValueAsUnsigned(0) == 0) {
|
|
|
|
stream.Printf("nullptr");
|
|
|
|
return true;
|
2016-09-06 20:57:50 +00:00
|
|
|
} else {
|
2014-01-08 01:36:59 +00:00
|
|
|
bool print_pointee = false;
|
2017-05-12 04:51:55 +00:00
|
|
|
Status error;
|
2014-12-09 19:51:20 +00:00
|
|
|
ValueObjectSP pointee_sp = ptr_sp->Dereference(error);
|
2014-01-08 01:36:59 +00:00
|
|
|
if (pointee_sp && error.Success()) {
|
|
|
|
if (pointee_sp->DumpPrintableRepresentation(
|
|
|
|
stream, ValueObject::eValueObjectRepresentationStyleSummary,
|
|
|
|
lldb::eFormatInvalid,
|
2016-11-07 23:32:20 +00:00
|
|
|
ValueObject::PrintableRepresentationSpecialCases::eDisable,
|
|
|
|
false))
|
2014-01-08 01:36:59 +00:00
|
|
|
print_pointee = true;
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2014-01-08 01:36:59 +00:00
|
|
|
if (!print_pointee)
|
|
|
|
stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0));
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
2014-01-08 01:36:59 +00:00
|
|
|
if (count_sp)
|
|
|
|
stream.Printf(" strong=%" PRIu64, 1 + count_sp->GetValueAsUnsigned(0));
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2014-01-08 01:36:59 +00:00
|
|
|
if (weakcount_sp)
|
2013-03-19 22:58:48 +00:00
|
|
|
stream.Printf(" weak=%" PRIu64, 1 + weakcount_sp->GetValueAsUnsigned(0));
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2014-01-08 01:36:59 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-03-23 11:42:41 -07:00
|
|
|
bool lldb_private::formatters::LibcxxUniquePointerSummaryProvider(
|
|
|
|
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
|
|
|
|
ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
|
|
|
|
if (!valobj_sp)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
ValueObjectSP ptr_sp(
|
|
|
|
valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true));
|
|
|
|
if (!ptr_sp)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
ptr_sp = GetValueOfLibCXXCompressedPair(*ptr_sp);
|
|
|
|
if (!ptr_sp)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (ptr_sp->GetValueAsUnsigned(0) == 0) {
|
|
|
|
stream.Printf("nullptr");
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
bool print_pointee = false;
|
|
|
|
Status error;
|
|
|
|
ValueObjectSP pointee_sp = ptr_sp->Dereference(error);
|
|
|
|
if (pointee_sp && error.Success()) {
|
|
|
|
if (pointee_sp->DumpPrintableRepresentation(
|
|
|
|
stream, ValueObject::eValueObjectRepresentationStyleSummary,
|
|
|
|
lldb::eFormatInvalid,
|
|
|
|
ValueObject::PrintableRepresentationSpecialCases::eDisable,
|
|
|
|
false))
|
|
|
|
print_pointee = true;
|
|
|
|
}
|
|
|
|
if (!print_pointee)
|
|
|
|
stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0));
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-02-21 19:57:10 +00:00
|
|
|
/*
|
|
|
|
(lldb) fr var ibeg --raw --ptr-depth 1
|
|
|
|
(std::__1::__map_iterator<std::__1::__tree_iterator<std::__1::pair<int,
|
|
|
|
std::__1::basic_string<char, std::__1::char_traits<char>,
|
|
|
|
std::__1::allocator<char> > >, std::__1::__tree_node<std::__1::pair<int,
|
|
|
|
std::__1::basic_string<char, std::__1::char_traits<char>,
|
|
|
|
std::__1::allocator<char> > >, void *> *, long> >) ibeg = {
|
|
|
|
__i_ = {
|
|
|
|
__ptr_ = 0x0000000100103870 {
|
|
|
|
std::__1::__tree_node_base<void *> = {
|
|
|
|
std::__1::__tree_end_node<std::__1::__tree_node_base<void *> *> = {
|
|
|
|
__left_ = 0x0000000000000000
|
|
|
|
}
|
|
|
|
__right_ = 0x0000000000000000
|
|
|
|
__parent_ = 0x00000001001038b0
|
|
|
|
__is_black_ = true
|
|
|
|
}
|
|
|
|
__value_ = {
|
|
|
|
first = 0
|
|
|
|
second = { std::string }
|
|
|
|
*/
|
|
|
|
|
|
|
|
lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
|
|
|
|
LibCxxMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
|
2016-09-28 22:53:16 +00:00
|
|
|
: SyntheticChildrenFrontEnd(*valobj_sp), m_pair_ptr(), m_pair_sp() {
|
2013-02-21 19:57:10 +00:00
|
|
|
if (valobj_sp)
|
|
|
|
Update();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() {
|
2016-09-28 22:53:16 +00:00
|
|
|
m_pair_sp.reset();
|
|
|
|
m_pair_ptr = nullptr;
|
|
|
|
|
2013-02-21 19:57:10 +00:00
|
|
|
ValueObjectSP valobj_sp = m_backend.GetSP();
|
|
|
|
if (!valobj_sp)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
TargetSP target_sp(valobj_sp->GetTargetSP());
|
|
|
|
|
|
|
|
if (!target_sp)
|
2013-03-19 22:58:48 +00:00
|
|
|
return false;
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2013-02-21 19:57:10 +00:00
|
|
|
if (!valobj_sp)
|
|
|
|
return false;
|
2018-08-15 22:48:48 +00:00
|
|
|
|
2022-02-16 11:51:50 -08:00
|
|
|
static ConstString g_i_("__i_");
|
2018-08-15 22:48:48 +00:00
|
|
|
|
2018-04-30 16:49:04 +00:00
|
|
|
// this must be a ValueObject* because it is a child of the ValueObject we
|
|
|
|
// are producing children for it if were a ValueObjectSP, we would end up
|
|
|
|
// with a loop (iterator -> synthetic -> child -> parent == iterator) and
|
|
|
|
// that would in turn leak memory by never allowing the ValueObjects to die
|
|
|
|
// and free their memory
|
2013-02-21 19:57:10 +00:00
|
|
|
m_pair_ptr = valobj_sp
|
|
|
|
->GetValueForExpressionPath(
|
2016-11-18 17:55:04 +00:00
|
|
|
".__i_.__ptr_->__value_", nullptr, nullptr,
|
2016-02-29 19:41:30 +00:00
|
|
|
ValueObject::GetValueForExpressionPathOptions()
|
|
|
|
.DontCheckDotVsArrowSyntax()
|
|
|
|
.SetSyntheticChildrenTraversal(
|
|
|
|
ValueObject::GetValueForExpressionPathOptions::
|
|
|
|
SyntheticChildrenTraversal::None),
|
2016-09-06 20:57:50 +00:00
|
|
|
nullptr)
|
|
|
|
.get();
|
2016-11-18 17:55:04 +00:00
|
|
|
|
2016-09-28 22:53:16 +00:00
|
|
|
if (!m_pair_ptr) {
|
2016-11-18 17:55:04 +00:00
|
|
|
m_pair_ptr = valobj_sp
|
|
|
|
->GetValueForExpressionPath(
|
|
|
|
".__i_.__ptr_", nullptr, nullptr,
|
|
|
|
ValueObject::GetValueForExpressionPathOptions()
|
|
|
|
.DontCheckDotVsArrowSyntax()
|
|
|
|
.SetSyntheticChildrenTraversal(
|
|
|
|
ValueObject::GetValueForExpressionPathOptions::
|
|
|
|
SyntheticChildrenTraversal::None),
|
|
|
|
nullptr)
|
|
|
|
.get();
|
2016-09-28 22:53:16 +00:00
|
|
|
if (m_pair_ptr) {
|
2022-02-16 11:51:50 -08:00
|
|
|
auto __i_(valobj_sp->GetChildMemberWithName(g_i_, true));
|
2016-09-28 22:53:16 +00:00
|
|
|
if (!__i_) {
|
|
|
|
m_pair_ptr = nullptr;
|
|
|
|
return false;
|
|
|
|
}
|
2019-01-15 18:07:52 +00:00
|
|
|
CompilerType pair_type(
|
|
|
|
__i_->GetCompilerType().GetTypeTemplateArgument(0));
|
|
|
|
std::string name;
|
|
|
|
uint64_t bit_offset_ptr;
|
|
|
|
uint32_t bitfield_bit_size_ptr;
|
|
|
|
bool is_bitfield_ptr;
|
|
|
|
pair_type = pair_type.GetFieldAtIndex(
|
|
|
|
0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr);
|
2016-09-28 22:53:16 +00:00
|
|
|
if (!pair_type) {
|
|
|
|
m_pair_ptr = nullptr;
|
|
|
|
return false;
|
|
|
|
}
|
2018-08-15 22:48:48 +00:00
|
|
|
|
2016-09-28 22:53:16 +00:00
|
|
|
auto addr(m_pair_ptr->GetValueAsUnsigned(LLDB_INVALID_ADDRESS));
|
|
|
|
m_pair_ptr = nullptr;
|
2019-01-15 18:07:52 +00:00
|
|
|
if (addr && addr != LLDB_INVALID_ADDRESS) {
|
2022-11-14 16:24:36 -08:00
|
|
|
auto ts = pair_type.GetTypeSystem();
|
|
|
|
auto ast_ctx = ts.dyn_cast_or_null<TypeSystemClang>();
|
2016-09-28 22:53:16 +00:00
|
|
|
if (!ast_ctx)
|
|
|
|
return false;
|
2022-07-08 10:47:04 +01:00
|
|
|
|
|
|
|
// Mimick layout of std::__tree_iterator::__ptr_ and read it in
|
|
|
|
// from process memory.
|
|
|
|
//
|
|
|
|
// The following shows the contiguous block of memory:
|
|
|
|
//
|
|
|
|
// +-----------------------------+ class __tree_end_node
|
|
|
|
// __ptr_ | pointer __left_; |
|
|
|
|
// +-----------------------------+ class __tree_node_base
|
|
|
|
// | pointer __right_; |
|
|
|
|
// | __parent_pointer __parent_; |
|
|
|
|
// | bool __is_black_; |
|
|
|
|
// +-----------------------------+ class __tree_node
|
|
|
|
// | __node_value_type __value_; | <<< our key/value pair
|
|
|
|
// +-----------------------------+
|
|
|
|
//
|
2019-01-15 18:07:52 +00:00
|
|
|
CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier(
|
|
|
|
ConstString(),
|
|
|
|
{{"ptr0",
|
|
|
|
ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
|
|
|
|
{"ptr1",
|
|
|
|
ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
|
|
|
|
{"ptr2",
|
|
|
|
ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
|
|
|
|
{"cw", ast_ctx->GetBasicType(lldb::eBasicTypeBool)},
|
|
|
|
{"payload", pair_type}});
|
2019-01-15 20:33:58 +00:00
|
|
|
llvm::Optional<uint64_t> size = tree_node_type.GetByteSize(nullptr);
|
2019-01-15 18:07:52 +00:00
|
|
|
if (!size)
|
|
|
|
return false;
|
2022-04-01 15:59:18 -07:00
|
|
|
WritableDataBufferSP buffer_sp(new DataBufferHeap(*size, 0));
|
2016-09-28 22:53:16 +00:00
|
|
|
ProcessSP process_sp(target_sp->GetProcessSP());
|
2017-05-12 04:51:55 +00:00
|
|
|
Status error;
|
2019-01-15 18:07:52 +00:00
|
|
|
process_sp->ReadMemory(addr, buffer_sp->GetBytes(),
|
|
|
|
buffer_sp->GetByteSize(), error);
|
2016-09-28 22:53:16 +00:00
|
|
|
if (error.Fail())
|
|
|
|
return false;
|
2019-01-15 18:07:52 +00:00
|
|
|
DataExtractor extractor(buffer_sp, process_sp->GetByteOrder(),
|
|
|
|
process_sp->GetAddressByteSize());
|
|
|
|
auto pair_sp = CreateValueObjectFromData(
|
|
|
|
"pair", extractor, valobj_sp->GetExecutionContextRef(),
|
|
|
|
tree_node_type);
|
2016-09-28 22:53:16 +00:00
|
|
|
if (pair_sp)
|
2019-01-15 18:07:52 +00:00
|
|
|
m_pair_sp = pair_sp->GetChildAtIndex(4, true);
|
2016-09-28 22:53:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2013-03-19 22:58:48 +00:00
|
|
|
return false;
|
2013-02-21 19:57:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
|
|
|
|
CalculateNumChildren() {
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
lldb::ValueObjectSP
|
|
|
|
lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetChildAtIndex(
|
|
|
|
size_t idx) {
|
2016-09-28 22:53:16 +00:00
|
|
|
if (m_pair_ptr)
|
|
|
|
return m_pair_ptr->GetChildAtIndex(idx, true);
|
|
|
|
if (m_pair_sp)
|
|
|
|
return m_pair_sp->GetChildAtIndex(idx, true);
|
|
|
|
return lldb::ValueObjectSP();
|
2013-02-21 19:57:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
|
|
|
|
MightHaveChildren() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
|
2019-03-06 21:22:25 +00:00
|
|
|
GetIndexOfChildWithName(ConstString name) {
|
Allow direct comparison of ConstString against StringRef
Summary:
When we want to compare a ConstString against a string literal (or any other non-ConstString),
we currently have to explicitly turn the other string into a ConstString. This makes sense as
comparing ConstStrings against each other is only a fast pointer comparison.
However, currently we (rather incorrectly) use in several places in LLDB temporary ConstStrings when
we just want to compare a given ConstString against a hardcoded value, for example like this:
```
if (extension != ConstString(".oat") && extension != ConstString(".odex"))
```
Obviously this kind of defeats the point of ConstStrings. In the comparison above we would
construct two temporary ConstStrings every time we hit the given code. Constructing a
ConstString is relatively expensive: we need to go to the StringPool, take a read and possibly
an exclusive write-lock and then look up our temporary string in the string map of the pool.
So we do a lot of heavy work for essentially just comparing a <6 characters in two strings.
I initially wanted to just fix these issues by turning the temporary ConstString in static variables/
members, but that made the code much less readable. Instead I propose to add a new overload
for the ConstString comparison operator that takes a StringRef. This comparison operator directly
compares the ConstString content against the given StringRef without turning the StringRef into
a ConstString.
This means that the example above can look like this now:
```
if (extension != ".oat" && extension != ".odex")
```
It also no longer has to unlock/lock two locks and call multiple functions in other TUs for constructing
the temporary ConstString instances. Instead this should end up just being a direct string comparison
of the two given strings on most compilers.
This patch also directly updates all uses of temporary and short ConstStrings in LLDB to use this new
comparison operator. It also adds a some unit tests for the new and old comparison operator.
Reviewers: #lldb, JDevlieghere, espindola, amccarth
Reviewed By: JDevlieghere, amccarth
Subscribers: amccarth, clayborg, JDevlieghere, emaste, arichardson, MaskRay, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D60667
llvm-svn: 359281
2019-04-26 07:21:36 +00:00
|
|
|
if (name == "first")
|
2013-02-21 19:57:10 +00:00
|
|
|
return 0;
|
Allow direct comparison of ConstString against StringRef
Summary:
When we want to compare a ConstString against a string literal (or any other non-ConstString),
we currently have to explicitly turn the other string into a ConstString. This makes sense as
comparing ConstStrings against each other is only a fast pointer comparison.
However, currently we (rather incorrectly) use in several places in LLDB temporary ConstStrings when
we just want to compare a given ConstString against a hardcoded value, for example like this:
```
if (extension != ConstString(".oat") && extension != ConstString(".odex"))
```
Obviously this kind of defeats the point of ConstStrings. In the comparison above we would
construct two temporary ConstStrings every time we hit the given code. Constructing a
ConstString is relatively expensive: we need to go to the StringPool, take a read and possibly
an exclusive write-lock and then look up our temporary string in the string map of the pool.
So we do a lot of heavy work for essentially just comparing a <6 characters in two strings.
I initially wanted to just fix these issues by turning the temporary ConstString in static variables/
members, but that made the code much less readable. Instead I propose to add a new overload
for the ConstString comparison operator that takes a StringRef. This comparison operator directly
compares the ConstString content against the given StringRef without turning the StringRef into
a ConstString.
This means that the example above can look like this now:
```
if (extension != ".oat" && extension != ".odex")
```
It also no longer has to unlock/lock two locks and call multiple functions in other TUs for constructing
the temporary ConstString instances. Instead this should end up just being a direct string comparison
of the two given strings on most compilers.
This patch also directly updates all uses of temporary and short ConstStrings in LLDB to use this new
comparison operator. It also adds a some unit tests for the new and old comparison operator.
Reviewers: #lldb, JDevlieghere, espindola, amccarth
Reviewed By: JDevlieghere, amccarth
Subscribers: amccarth, clayborg, JDevlieghere, emaste, arichardson, MaskRay, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D60667
llvm-svn: 359281
2019-04-26 07:21:36 +00:00
|
|
|
if (name == "second")
|
2013-02-21 19:57:10 +00:00
|
|
|
return 1;
|
|
|
|
return UINT32_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
|
|
|
|
~LibCxxMapIteratorSyntheticFrontEnd() {
|
|
|
|
// this will be deleted when its parent dies (since it's a child object)
|
|
|
|
// delete m_pair_ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
SyntheticChildrenFrontEnd *
|
|
|
|
lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator(
|
|
|
|
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
|
2016-02-29 19:41:30 +00:00
|
|
|
return (valobj_sp ? new LibCxxMapIteratorSyntheticFrontEnd(valobj_sp)
|
|
|
|
: nullptr);
|
2013-02-21 19:57:10 +00:00
|
|
|
}
|
|
|
|
|
2022-07-08 10:47:04 +01:00
|
|
|
lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEnd::
|
|
|
|
LibCxxUnorderedMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
|
|
|
|
: SyntheticChildrenFrontEnd(*valobj_sp) {
|
|
|
|
if (valobj_sp)
|
|
|
|
Update();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEnd::
|
|
|
|
Update() {
|
|
|
|
m_pair_sp.reset();
|
|
|
|
m_iter_ptr = nullptr;
|
|
|
|
|
|
|
|
ValueObjectSP valobj_sp = m_backend.GetSP();
|
|
|
|
if (!valobj_sp)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
TargetSP target_sp(valobj_sp->GetTargetSP());
|
|
|
|
|
|
|
|
if (!target_sp)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!valobj_sp)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
auto exprPathOptions = ValueObject::GetValueForExpressionPathOptions()
|
|
|
|
.DontCheckDotVsArrowSyntax()
|
|
|
|
.SetSyntheticChildrenTraversal(
|
|
|
|
ValueObject::GetValueForExpressionPathOptions::
|
|
|
|
SyntheticChildrenTraversal::None);
|
|
|
|
|
|
|
|
// This must be a ValueObject* because it is a child of the ValueObject we
|
|
|
|
// are producing children for it if were a ValueObjectSP, we would end up
|
|
|
|
// with a loop (iterator -> synthetic -> child -> parent == iterator) and
|
|
|
|
// that would in turn leak memory by never allowing the ValueObjects to die
|
|
|
|
// and free their memory.
|
|
|
|
m_iter_ptr =
|
|
|
|
valobj_sp
|
|
|
|
->GetValueForExpressionPath(".__i_.__node_", nullptr, nullptr,
|
|
|
|
exprPathOptions, nullptr)
|
|
|
|
.get();
|
|
|
|
|
|
|
|
if (m_iter_ptr) {
|
|
|
|
auto iter_child(
|
|
|
|
valobj_sp->GetChildMemberWithName(ConstString("__i_"), true));
|
|
|
|
if (!iter_child) {
|
|
|
|
m_iter_ptr = nullptr;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
CompilerType node_type(iter_child->GetCompilerType()
|
|
|
|
.GetTypeTemplateArgument(0)
|
|
|
|
.GetPointeeType());
|
|
|
|
|
|
|
|
CompilerType pair_type(node_type.GetTypeTemplateArgument(0));
|
|
|
|
|
|
|
|
std::string name;
|
|
|
|
uint64_t bit_offset_ptr;
|
|
|
|
uint32_t bitfield_bit_size_ptr;
|
|
|
|
bool is_bitfield_ptr;
|
|
|
|
|
|
|
|
pair_type = pair_type.GetFieldAtIndex(
|
|
|
|
0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr);
|
|
|
|
if (!pair_type) {
|
|
|
|
m_iter_ptr = nullptr;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t addr = m_iter_ptr->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
|
|
|
|
m_iter_ptr = nullptr;
|
|
|
|
|
|
|
|
if (addr == 0 || addr == LLDB_INVALID_ADDRESS)
|
|
|
|
return false;
|
|
|
|
|
2022-11-14 16:24:36 -08:00
|
|
|
auto ts = pair_type.GetTypeSystem();
|
|
|
|
auto ast_ctx = ts.dyn_cast_or_null<TypeSystemClang>();
|
2022-07-08 10:47:04 +01:00
|
|
|
if (!ast_ctx)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Mimick layout of std::__hash_iterator::__node_ and read it in
|
|
|
|
// from process memory.
|
|
|
|
//
|
|
|
|
// The following shows the contiguous block of memory:
|
|
|
|
//
|
|
|
|
// +-----------------------------+ class __hash_node_base
|
|
|
|
// __node_ | __next_pointer __next_; |
|
|
|
|
// +-----------------------------+ class __hash_node
|
|
|
|
// | size_t __hash_; |
|
|
|
|
// | __node_value_type __value_; | <<< our key/value pair
|
|
|
|
// +-----------------------------+
|
|
|
|
//
|
|
|
|
CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier(
|
|
|
|
ConstString(),
|
|
|
|
{{"__next_",
|
|
|
|
ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
|
|
|
|
{"__hash_", ast_ctx->GetBasicType(lldb::eBasicTypeUnsignedLongLong)},
|
|
|
|
{"__value_", pair_type}});
|
|
|
|
llvm::Optional<uint64_t> size = tree_node_type.GetByteSize(nullptr);
|
|
|
|
if (!size)
|
|
|
|
return false;
|
|
|
|
WritableDataBufferSP buffer_sp(new DataBufferHeap(*size, 0));
|
|
|
|
ProcessSP process_sp(target_sp->GetProcessSP());
|
|
|
|
Status error;
|
|
|
|
process_sp->ReadMemory(addr, buffer_sp->GetBytes(),
|
|
|
|
buffer_sp->GetByteSize(), error);
|
|
|
|
if (error.Fail())
|
|
|
|
return false;
|
|
|
|
DataExtractor extractor(buffer_sp, process_sp->GetByteOrder(),
|
|
|
|
process_sp->GetAddressByteSize());
|
|
|
|
auto pair_sp = CreateValueObjectFromData(
|
|
|
|
"pair", extractor, valobj_sp->GetExecutionContextRef(), tree_node_type);
|
|
|
|
if (pair_sp)
|
|
|
|
m_pair_sp = pair_sp->GetChildAtIndex(2, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEnd::
|
|
|
|
CalculateNumChildren() {
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
lldb::ValueObjectSP lldb_private::formatters::
|
|
|
|
LibCxxUnorderedMapIteratorSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
|
|
|
|
if (m_pair_sp)
|
|
|
|
return m_pair_sp->GetChildAtIndex(idx, true);
|
|
|
|
return lldb::ValueObjectSP();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEnd::
|
|
|
|
MightHaveChildren() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEnd::
|
|
|
|
GetIndexOfChildWithName(ConstString name) {
|
|
|
|
if (name == "first")
|
|
|
|
return 0;
|
|
|
|
if (name == "second")
|
|
|
|
return 1;
|
|
|
|
return UINT32_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
SyntheticChildrenFrontEnd *
|
|
|
|
lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEndCreator(
|
|
|
|
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
|
|
|
|
return (valobj_sp ? new LibCxxUnorderedMapIteratorSyntheticFrontEnd(valobj_sp)
|
|
|
|
: nullptr);
|
|
|
|
}
|
|
|
|
|
2013-02-21 19:57:10 +00:00
|
|
|
/*
|
|
|
|
(lldb) fr var ibeg --raw --ptr-depth 1 -T
|
|
|
|
(std::__1::__wrap_iter<int *>) ibeg = {
|
|
|
|
(std::__1::__wrap_iter<int *>::iterator_type) __i = 0x00000001001037a0 {
|
|
|
|
(int) *__i = 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
SyntheticChildrenFrontEnd *
|
|
|
|
lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator(
|
|
|
|
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
|
2022-09-09 15:58:14 -07:00
|
|
|
return (valobj_sp ? new VectorIteratorSyntheticFrontEnd(
|
|
|
|
valobj_sp, {ConstString("__i_"), ConstString("__i")})
|
|
|
|
: nullptr);
|
2013-02-21 19:57:10 +00:00
|
|
|
}
|
2013-03-19 22:58:48 +00:00
|
|
|
|
|
|
|
lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
|
|
|
|
LibcxxSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
|
2021-02-21 14:38:43 -08:00
|
|
|
: SyntheticChildrenFrontEnd(*valobj_sp), m_cntrl(nullptr) {
|
2013-03-19 22:58:48 +00:00
|
|
|
if (valobj_sp)
|
|
|
|
Update();
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
|
|
|
|
CalculateNumChildren() {
|
|
|
|
return (m_cntrl ? 1 : 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
lldb::ValueObjectSP
|
|
|
|
lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex(
|
|
|
|
size_t idx) {
|
|
|
|
if (!m_cntrl)
|
|
|
|
return lldb::ValueObjectSP();
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2013-03-19 22:58:48 +00:00
|
|
|
ValueObjectSP valobj_sp = m_backend.GetSP();
|
|
|
|
if (!valobj_sp)
|
|
|
|
return lldb::ValueObjectSP();
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2013-03-19 22:58:48 +00:00
|
|
|
if (idx == 0)
|
|
|
|
return valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true);
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2013-03-19 22:58:48 +00:00
|
|
|
if (idx == 1) {
|
2021-02-21 14:38:43 -08:00
|
|
|
if (auto ptr_sp =
|
|
|
|
valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true)) {
|
|
|
|
Status status;
|
|
|
|
auto value_sp = ptr_sp->Dereference(status);
|
|
|
|
if (status.Success()) {
|
|
|
|
auto value_type_sp =
|
|
|
|
valobj_sp->GetCompilerType().GetTypeTemplateArgument(0);
|
|
|
|
return value_sp->Cast(value_type_sp);
|
|
|
|
}
|
2013-03-19 22:58:48 +00:00
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2021-02-21 14:38:43 -08:00
|
|
|
|
|
|
|
return lldb::ValueObjectSP();
|
2013-03-19 22:58:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() {
|
2016-02-29 19:41:30 +00:00
|
|
|
m_cntrl = nullptr;
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2013-03-19 22:58:48 +00:00
|
|
|
ValueObjectSP valobj_sp = m_backend.GetSP();
|
|
|
|
if (!valobj_sp)
|
|
|
|
return false;
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2013-03-19 22:58:48 +00:00
|
|
|
TargetSP target_sp(valobj_sp->GetTargetSP());
|
2013-02-21 19:57:10 +00:00
|
|
|
if (!target_sp)
|
2013-03-19 22:58:48 +00:00
|
|
|
return false;
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2013-03-19 22:58:48 +00:00
|
|
|
lldb::ValueObjectSP cntrl_sp(
|
|
|
|
valobj_sp->GetChildMemberWithName(ConstString("__cntrl_"), true));
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2013-03-19 22:58:48 +00:00
|
|
|
m_cntrl = cntrl_sp.get(); // need to store the raw pointer to avoid a circular
|
|
|
|
// dependency
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
|
|
|
|
MightHaveChildren() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
|
2019-03-06 21:22:25 +00:00
|
|
|
GetIndexOfChildWithName(ConstString name) {
|
Allow direct comparison of ConstString against StringRef
Summary:
When we want to compare a ConstString against a string literal (or any other non-ConstString),
we currently have to explicitly turn the other string into a ConstString. This makes sense as
comparing ConstStrings against each other is only a fast pointer comparison.
However, currently we (rather incorrectly) use in several places in LLDB temporary ConstStrings when
we just want to compare a given ConstString against a hardcoded value, for example like this:
```
if (extension != ConstString(".oat") && extension != ConstString(".odex"))
```
Obviously this kind of defeats the point of ConstStrings. In the comparison above we would
construct two temporary ConstStrings every time we hit the given code. Constructing a
ConstString is relatively expensive: we need to go to the StringPool, take a read and possibly
an exclusive write-lock and then look up our temporary string in the string map of the pool.
So we do a lot of heavy work for essentially just comparing a <6 characters in two strings.
I initially wanted to just fix these issues by turning the temporary ConstString in static variables/
members, but that made the code much less readable. Instead I propose to add a new overload
for the ConstString comparison operator that takes a StringRef. This comparison operator directly
compares the ConstString content against the given StringRef without turning the StringRef into
a ConstString.
This means that the example above can look like this now:
```
if (extension != ".oat" && extension != ".odex")
```
It also no longer has to unlock/lock two locks and call multiple functions in other TUs for constructing
the temporary ConstString instances. Instead this should end up just being a direct string comparison
of the two given strings on most compilers.
This patch also directly updates all uses of temporary and short ConstStrings in LLDB to use this new
comparison operator. It also adds a some unit tests for the new and old comparison operator.
Reviewers: #lldb, JDevlieghere, espindola, amccarth
Reviewed By: JDevlieghere, amccarth
Subscribers: amccarth, clayborg, JDevlieghere, emaste, arichardson, MaskRay, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D60667
llvm-svn: 359281
2019-04-26 07:21:36 +00:00
|
|
|
if (name == "__ptr_")
|
2013-03-19 22:58:48 +00:00
|
|
|
return 0;
|
2021-02-21 14:38:43 -08:00
|
|
|
if (name == "$$dereference$$")
|
2013-03-19 22:58:48 +00:00
|
|
|
return 1;
|
|
|
|
return UINT32_MAX;
|
|
|
|
}
|
|
|
|
|
2016-02-29 19:41:30 +00:00
|
|
|
lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
|
|
|
|
~LibcxxSharedPtrSyntheticFrontEnd() = default;
|
2013-03-19 22:58:48 +00:00
|
|
|
|
|
|
|
SyntheticChildrenFrontEnd *
|
|
|
|
lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator(
|
|
|
|
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
|
2016-02-29 19:41:30 +00:00
|
|
|
return (valobj_sp ? new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp)
|
|
|
|
: nullptr);
|
2013-03-19 22:58:48 +00:00
|
|
|
}
|
|
|
|
|
2020-03-23 11:42:41 -07:00
|
|
|
lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
|
|
|
|
LibcxxUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
|
2021-02-25 13:27:22 -08:00
|
|
|
: SyntheticChildrenFrontEnd(*valobj_sp) {
|
2020-03-23 11:42:41 -07:00
|
|
|
if (valobj_sp)
|
|
|
|
Update();
|
|
|
|
}
|
|
|
|
|
|
|
|
lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
|
|
|
|
~LibcxxUniquePtrSyntheticFrontEnd() = default;
|
|
|
|
|
|
|
|
SyntheticChildrenFrontEnd *
|
|
|
|
lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEndCreator(
|
|
|
|
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
|
|
|
|
return (valobj_sp ? new LibcxxUniquePtrSyntheticFrontEnd(valobj_sp)
|
|
|
|
: nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
|
|
|
|
CalculateNumChildren() {
|
2021-02-25 13:27:22 -08:00
|
|
|
return (m_value_ptr_sp ? 1 : 0);
|
2020-03-23 11:42:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
lldb::ValueObjectSP
|
|
|
|
lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::GetChildAtIndex(
|
|
|
|
size_t idx) {
|
2021-02-25 13:27:22 -08:00
|
|
|
if (!m_value_ptr_sp)
|
2020-03-23 11:42:41 -07:00
|
|
|
return lldb::ValueObjectSP();
|
|
|
|
|
2021-02-25 13:27:22 -08:00
|
|
|
if (idx == 0)
|
|
|
|
return m_value_ptr_sp;
|
2020-03-23 11:42:41 -07:00
|
|
|
|
2021-02-25 13:27:22 -08:00
|
|
|
if (idx == 1) {
|
|
|
|
Status status;
|
|
|
|
auto value_sp = m_value_ptr_sp->Dereference(status);
|
|
|
|
if (status.Success()) {
|
|
|
|
return value_sp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return lldb::ValueObjectSP();
|
2020-03-23 11:42:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
bool lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::Update() {
|
|
|
|
ValueObjectSP valobj_sp = m_backend.GetSP();
|
|
|
|
if (!valobj_sp)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
ValueObjectSP ptr_sp(
|
|
|
|
valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true));
|
|
|
|
if (!ptr_sp)
|
|
|
|
return false;
|
|
|
|
|
2021-02-25 13:27:22 -08:00
|
|
|
m_value_ptr_sp = GetValueOfLibCXXCompressedPair(*ptr_sp);
|
2020-03-23 11:42:41 -07:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
|
|
|
|
MightHaveChildren() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
|
|
|
|
GetIndexOfChildWithName(ConstString name) {
|
|
|
|
if (name == "__value_")
|
|
|
|
return 0;
|
2021-02-25 13:27:22 -08:00
|
|
|
if (name == "$$dereference$$")
|
|
|
|
return 1;
|
2020-03-23 11:42:41 -07:00
|
|
|
return UINT32_MAX;
|
|
|
|
}
|
|
|
|
|
2014-11-06 21:55:30 +00:00
|
|
|
bool lldb_private::formatters::LibcxxContainerSummaryProvider(
|
|
|
|
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
|
2013-05-06 18:55:52 +00:00
|
|
|
if (valobj.IsPointerType()) {
|
|
|
|
uint64_t value = valobj.GetValueAsUnsigned(0);
|
|
|
|
if (!value)
|
|
|
|
return false;
|
2013-06-03 18:00:07 +00:00
|
|
|
stream.Printf("0x%016" PRIx64 " ", value);
|
2013-05-06 18:55:52 +00:00
|
|
|
}
|
2016-02-29 19:41:30 +00:00
|
|
|
return FormatEntity::FormatStringRef("size=${svar%#}", stream, nullptr,
|
|
|
|
nullptr, nullptr, &valobj, false, false);
|
2013-05-06 18:55:52 +00:00
|
|
|
}
|
2015-09-03 01:29:42 +00:00
|
|
|
|
2022-05-20 11:24:24 -07:00
|
|
|
/// The field layout in a libc++ string (cap, side, data or data, size, cap).
|
2022-07-11 16:56:04 +02:00
|
|
|
namespace {
|
|
|
|
enum class StringLayout { CSD, DSC };
|
|
|
|
}
|
2015-09-03 01:29:42 +00:00
|
|
|
|
2020-02-05 09:46:51 -08:00
|
|
|
/// Determine the size in bytes of \p valobj (a libc++ std::string object) and
|
|
|
|
/// extract its data payload. Return the size + payload pair.
|
2022-04-20 20:52:14 +02:00
|
|
|
// TODO: Support big-endian architectures.
|
2020-02-05 09:46:51 -08:00
|
|
|
static llvm::Optional<std::pair<uint64_t, ValueObjectSP>>
|
|
|
|
ExtractLibcxxStringInfo(ValueObject &valobj) {
|
2022-07-11 16:56:04 +02:00
|
|
|
ValueObjectSP valobj_r_sp =
|
|
|
|
valobj.GetChildMemberWithName(ConstString("__r_"), /*can_create=*/true);
|
2022-07-12 20:05:20 +02:00
|
|
|
if (!valobj_r_sp || !valobj_r_sp->GetError().Success())
|
2022-05-17 08:21:09 -07:00
|
|
|
return {};
|
2022-07-11 16:56:04 +02:00
|
|
|
|
|
|
|
// __r_ is a compressed_pair of the actual data and the allocator. The data we
|
|
|
|
// want is in the first base class.
|
|
|
|
ValueObjectSP valobj_r_base_sp =
|
|
|
|
valobj_r_sp->GetChildAtIndex(0, /*can_create=*/true);
|
|
|
|
if (!valobj_r_base_sp)
|
2020-02-05 09:46:51 -08:00
|
|
|
return {};
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2022-07-11 16:56:04 +02:00
|
|
|
ValueObjectSP valobj_rep_sp = valobj_r_base_sp->GetChildMemberWithName(
|
|
|
|
ConstString("__value_"), /*can_create=*/true);
|
|
|
|
if (!valobj_rep_sp)
|
|
|
|
return {};
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2022-07-11 16:56:04 +02:00
|
|
|
ValueObjectSP l = valobj_rep_sp->GetChildMemberWithName(ConstString("__l"),
|
|
|
|
/*can_create=*/true);
|
|
|
|
if (!l)
|
2020-02-05 09:46:51 -08:00
|
|
|
return {};
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2022-07-11 16:56:04 +02:00
|
|
|
StringLayout layout = l->GetIndexOfChildWithName(ConstString("__data_")) == 0
|
|
|
|
? StringLayout::DSC
|
|
|
|
: StringLayout::CSD;
|
|
|
|
|
2015-09-03 01:29:42 +00:00
|
|
|
bool short_mode = false; // this means the string is in short-mode and the
|
|
|
|
// data is stored inline
|
2022-04-20 20:52:14 +02:00
|
|
|
bool using_bitmasks = true; // Whether the class uses bitmasks for the mode
|
|
|
|
// flag (pre-D123580).
|
|
|
|
uint64_t size;
|
2015-09-03 01:29:42 +00:00
|
|
|
uint64_t size_mode_value = 0;
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2022-07-11 16:56:04 +02:00
|
|
|
ValueObjectSP short_sp = valobj_rep_sp->GetChildMemberWithName(
|
|
|
|
ConstString("__s"), /*can_create=*/true);
|
2022-06-27 18:28:30 -07:00
|
|
|
if (!short_sp)
|
|
|
|
return {};
|
|
|
|
|
2022-06-30 16:30:51 +02:00
|
|
|
ValueObjectSP is_long =
|
|
|
|
short_sp->GetChildMemberWithName(ConstString("__is_long_"), true);
|
2022-07-11 16:56:04 +02:00
|
|
|
ValueObjectSP size_sp =
|
|
|
|
short_sp->GetChildAtNamePath({ConstString("__size_")});
|
|
|
|
if (!size_sp)
|
|
|
|
return {};
|
2022-06-27 18:28:30 -07:00
|
|
|
|
2022-06-30 16:30:51 +02:00
|
|
|
if (is_long) {
|
2022-04-20 20:52:14 +02:00
|
|
|
using_bitmasks = false;
|
|
|
|
short_mode = !is_long->GetValueAsUnsigned(/*fail_value=*/0);
|
2022-07-11 16:56:04 +02:00
|
|
|
size = size_sp->GetValueAsUnsigned(/*fail_value=*/0);
|
2016-09-06 20:57:50 +00:00
|
|
|
} else {
|
2022-07-11 16:56:04 +02:00
|
|
|
// The string mode is encoded in the size field.
|
|
|
|
size_mode_value = size_sp->GetValueAsUnsigned(0);
|
|
|
|
uint8_t mode_mask = layout == StringLayout::DSC ? 0x80 : 1;
|
|
|
|
short_mode = (size_mode_value & mode_mask) == 0;
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
2015-09-03 01:29:42 +00:00
|
|
|
if (short_mode) {
|
2022-06-30 16:30:51 +02:00
|
|
|
ValueObjectSP location_sp =
|
2022-07-11 16:56:04 +02:00
|
|
|
short_sp->GetChildMemberWithName(ConstString("__data_"), true);
|
2022-04-20 20:52:14 +02:00
|
|
|
if (using_bitmasks)
|
2022-07-11 16:56:04 +02:00
|
|
|
size = (layout == StringLayout::DSC) ? size_mode_value
|
|
|
|
: ((size_mode_value >> 1) % 256);
|
2020-01-31 23:18:17 -08:00
|
|
|
|
|
|
|
// When the small-string optimization takes place, the data must fit in the
|
|
|
|
// inline string buffer (23 bytes on x86_64/Darwin). If it doesn't, it's
|
|
|
|
// likely that the string isn't initialized and we're reading garbage.
|
|
|
|
ExecutionContext exe_ctx(location_sp->GetExecutionContextRef());
|
|
|
|
const llvm::Optional<uint64_t> max_bytes =
|
|
|
|
location_sp->GetCompilerType().GetByteSize(
|
|
|
|
exe_ctx.GetBestExecutionContextScope());
|
2020-02-05 09:46:51 -08:00
|
|
|
if (!max_bytes || size > *max_bytes || !location_sp)
|
|
|
|
return {};
|
2020-01-31 23:18:17 -08:00
|
|
|
|
2020-02-05 09:46:51 -08:00
|
|
|
return std::make_pair(size, location_sp);
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2020-02-05 09:46:51 -08:00
|
|
|
|
|
|
|
// we can use the layout_decider object as the data pointer
|
2022-04-20 20:52:14 +02:00
|
|
|
ValueObjectSP location_sp =
|
|
|
|
l->GetChildMemberWithName(ConstString("__data_"), /*can_create=*/true);
|
|
|
|
ValueObjectSP size_vo =
|
|
|
|
l->GetChildMemberWithName(ConstString("__size_"), /*can_create=*/true);
|
2022-06-30 16:30:51 +02:00
|
|
|
ValueObjectSP capacity_vo =
|
|
|
|
l->GetChildMemberWithName(ConstString("__cap_"), /*can_create=*/true);
|
2020-02-05 09:46:51 -08:00
|
|
|
if (!size_vo || !location_sp || !capacity_vo)
|
|
|
|
return {};
|
2022-04-20 20:52:14 +02:00
|
|
|
size = size_vo->GetValueAsUnsigned(LLDB_INVALID_OFFSET);
|
|
|
|
uint64_t capacity = capacity_vo->GetValueAsUnsigned(LLDB_INVALID_OFFSET);
|
2022-07-11 16:56:04 +02:00
|
|
|
if (!using_bitmasks && layout == StringLayout::CSD)
|
2022-04-20 20:52:14 +02:00
|
|
|
capacity *= 2;
|
2020-02-05 09:46:51 -08:00
|
|
|
if (size == LLDB_INVALID_OFFSET || capacity == LLDB_INVALID_OFFSET ||
|
|
|
|
capacity < size)
|
|
|
|
return {};
|
|
|
|
return std::make_pair(size, location_sp);
|
2015-09-03 01:29:42 +00:00
|
|
|
}
|
|
|
|
|
2022-01-07 11:38:47 -08:00
|
|
|
static bool
|
|
|
|
LibcxxWStringSummaryProvider(ValueObject &valobj, Stream &stream,
|
|
|
|
const TypeSummaryOptions &summary_options,
|
|
|
|
ValueObjectSP location_sp, size_t size) {
|
2015-09-03 01:29:42 +00:00
|
|
|
if (size == 0) {
|
2015-11-04 00:02:08 +00:00
|
|
|
stream.Printf("L\"\"");
|
|
|
|
return true;
|
|
|
|
}
|
2015-09-03 01:29:42 +00:00
|
|
|
if (!location_sp)
|
|
|
|
return false;
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2015-09-09 22:30:24 +00:00
|
|
|
StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
|
|
|
|
if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) {
|
|
|
|
const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
|
2015-11-04 00:02:08 +00:00
|
|
|
if (size > max_size) {
|
|
|
|
size = max_size;
|
2015-09-09 22:30:24 +00:00
|
|
|
options.SetIsTruncated(true);
|
2015-09-03 01:29:42 +00:00
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2020-02-05 09:46:51 -08:00
|
|
|
|
|
|
|
DataExtractor extractor;
|
2020-01-31 23:18:17 -08:00
|
|
|
const size_t bytes_read = location_sp->GetPointeeData(extractor, 0, size);
|
|
|
|
if (bytes_read < size)
|
|
|
|
return false;
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2015-09-03 01:29:42 +00:00
|
|
|
// std::wstring::size() is measured in 'characters', not bytes
|
[lldb][NFC] Rename ClangASTContext to TypeSystemClang
Summary:
This commit renames ClangASTContext to TypeSystemClang to better reflect what this class is actually supposed to do
(implement the TypeSystem interface for Clang). It also gets rid of the very confusing situation that we have both a
`clang::ASTContext` and a `ClangASTContext` in clang (which sometimes causes Clang people to think I'm fiddling
with Clang's ASTContext when I'm actually just doing LLDB work).
I also have plans to potentially have multiple clang::ASTContext instances associated with one ClangASTContext so
the ASTContext naming will then become even more confusing to people.
Reviewers: #lldb, aprantl, shafik, clayborg, labath, JDevlieghere, davide, espindola, jdoerfert, xiaobai
Reviewed By: clayborg, labath, xiaobai
Subscribers: wuzish, emaste, nemanjai, mgorny, kbarton, MaskRay, arphaman, jfb, usaxena95, jingham, xiaobai, abidh, JDevlieghere, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D72684
2020-01-23 10:04:13 +01:00
|
|
|
TypeSystemClang *ast_context =
|
2020-12-04 10:26:03 +01:00
|
|
|
ScratchTypeSystemClang::GetForTarget(*valobj.GetTargetSP());
|
2019-11-14 13:41:52 -08:00
|
|
|
if (!ast_context)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
auto wchar_t_size =
|
|
|
|
ast_context->GetBasicType(lldb::eBasicTypeWChar).GetByteSize(nullptr);
|
2019-01-15 18:07:52 +00:00
|
|
|
if (!wchar_t_size)
|
|
|
|
return false;
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2021-08-04 20:34:21 +02:00
|
|
|
options.SetData(std::move(extractor));
|
2015-09-03 01:29:42 +00:00
|
|
|
options.SetStream(&stream);
|
2015-10-07 02:06:48 +00:00
|
|
|
options.SetPrefixToken("L");
|
2015-09-03 01:29:42 +00:00
|
|
|
options.SetQuote('"');
|
|
|
|
options.SetSourceSize(size);
|
|
|
|
options.SetBinaryZeroIsTerminator(false);
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2019-01-15 18:07:52 +00:00
|
|
|
switch (*wchar_t_size) {
|
2016-09-06 20:57:50 +00:00
|
|
|
case 1:
|
2020-01-31 23:18:17 -08:00
|
|
|
return StringPrinter::ReadBufferAndDumpToStream<
|
2015-09-09 22:30:24 +00:00
|
|
|
lldb_private::formatters::StringPrinter::StringElementType::UTF8>(
|
2016-09-06 20:57:50 +00:00
|
|
|
options);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
2020-01-31 23:18:17 -08:00
|
|
|
return StringPrinter::ReadBufferAndDumpToStream<
|
2015-09-09 22:30:24 +00:00
|
|
|
lldb_private::formatters::StringPrinter::StringElementType::UTF16>(
|
2016-09-06 20:57:50 +00:00
|
|
|
options);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
2020-01-31 23:18:17 -08:00
|
|
|
return StringPrinter::ReadBufferAndDumpToStream<
|
2015-09-09 22:30:24 +00:00
|
|
|
lldb_private::formatters::StringPrinter::StringElementType::UTF32>(
|
2016-09-06 20:57:50 +00:00
|
|
|
options);
|
|
|
|
}
|
2020-01-31 23:18:17 -08:00
|
|
|
return false;
|
2015-09-03 01:29:42 +00:00
|
|
|
}
|
|
|
|
|
2022-01-07 11:38:47 -08:00
|
|
|
bool lldb_private::formatters::LibcxxWStringSummaryProvider(
|
|
|
|
ValueObject &valobj, Stream &stream,
|
|
|
|
const TypeSummaryOptions &summary_options) {
|
2020-02-05 09:46:51 -08:00
|
|
|
auto string_info = ExtractLibcxxStringInfo(valobj);
|
|
|
|
if (!string_info)
|
2015-09-03 01:29:42 +00:00
|
|
|
return false;
|
2020-02-05 09:46:51 -08:00
|
|
|
uint64_t size;
|
|
|
|
ValueObjectSP location_sp;
|
|
|
|
std::tie(size, location_sp) = *string_info;
|
|
|
|
|
2022-01-07 11:38:47 -08:00
|
|
|
return ::LibcxxWStringSummaryProvider(valobj, stream, summary_options,
|
|
|
|
location_sp, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <StringPrinter::StringElementType element_type>
|
|
|
|
static bool
|
|
|
|
LibcxxStringSummaryProvider(ValueObject &valobj, Stream &stream,
|
|
|
|
const TypeSummaryOptions &summary_options,
|
|
|
|
std::string prefix_token, ValueObjectSP location_sp,
|
|
|
|
uint64_t size) {
|
|
|
|
|
2015-09-03 01:29:42 +00:00
|
|
|
if (size == 0) {
|
2015-09-09 22:30:24 +00:00
|
|
|
stream.Printf("\"\"");
|
2015-09-03 01:29:42 +00:00
|
|
|
return true;
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
2015-09-03 01:29:42 +00:00
|
|
|
if (!location_sp)
|
|
|
|
return false;
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2015-11-04 00:02:08 +00:00
|
|
|
StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2015-09-03 01:29:42 +00:00
|
|
|
if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) {
|
2015-11-04 00:02:08 +00:00
|
|
|
const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
|
|
|
|
if (size > max_size) {
|
|
|
|
size = max_size;
|
|
|
|
options.SetIsTruncated(true);
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
}
|
2020-02-05 09:46:51 -08:00
|
|
|
|
2021-08-04 20:34:21 +02:00
|
|
|
{
|
|
|
|
DataExtractor extractor;
|
|
|
|
const size_t bytes_read = location_sp->GetPointeeData(extractor, 0, size);
|
|
|
|
if (bytes_read < size)
|
|
|
|
return false;
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2021-08-04 20:34:21 +02:00
|
|
|
options.SetData(std::move(extractor));
|
|
|
|
}
|
2015-09-03 01:29:42 +00:00
|
|
|
options.SetStream(&stream);
|
2018-10-26 17:00:48 +00:00
|
|
|
if (prefix_token.empty())
|
|
|
|
options.SetPrefixToken(nullptr);
|
|
|
|
else
|
|
|
|
options.SetPrefixToken(prefix_token);
|
2015-09-03 01:29:42 +00:00
|
|
|
options.SetQuote('"');
|
|
|
|
options.SetSourceSize(size);
|
|
|
|
options.SetBinaryZeroIsTerminator(false);
|
2020-01-31 23:18:17 -08:00
|
|
|
return StringPrinter::ReadBufferAndDumpToStream<element_type>(options);
|
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2022-01-07 11:38:47 -08:00
|
|
|
template <StringPrinter::StringElementType element_type>
|
|
|
|
static bool
|
|
|
|
LibcxxStringSummaryProvider(ValueObject &valobj, Stream &stream,
|
|
|
|
const TypeSummaryOptions &summary_options,
|
|
|
|
std::string prefix_token) {
|
|
|
|
auto string_info = ExtractLibcxxStringInfo(valobj);
|
|
|
|
if (!string_info)
|
|
|
|
return false;
|
|
|
|
uint64_t size;
|
|
|
|
ValueObjectSP location_sp;
|
|
|
|
std::tie(size, location_sp) = *string_info;
|
|
|
|
|
|
|
|
return LibcxxStringSummaryProvider<element_type>(
|
|
|
|
valobj, stream, summary_options, prefix_token, location_sp, size);
|
|
|
|
}
|
2020-01-31 23:18:17 -08:00
|
|
|
template <StringPrinter::StringElementType element_type>
|
|
|
|
static bool formatStringImpl(ValueObject &valobj, Stream &stream,
|
|
|
|
const TypeSummaryOptions &summary_options,
|
|
|
|
std::string prefix_token) {
|
|
|
|
StreamString scratch_stream;
|
|
|
|
const bool success = LibcxxStringSummaryProvider<element_type>(
|
|
|
|
valobj, scratch_stream, summary_options, prefix_token);
|
|
|
|
if (success)
|
|
|
|
stream << scratch_stream.GetData();
|
|
|
|
else
|
|
|
|
stream << "Summary Unavailable";
|
2015-09-03 01:29:42 +00:00
|
|
|
return true;
|
|
|
|
}
|
2018-10-26 17:00:48 +00:00
|
|
|
|
|
|
|
bool lldb_private::formatters::LibcxxStringSummaryProviderASCII(
|
|
|
|
ValueObject &valobj, Stream &stream,
|
|
|
|
const TypeSummaryOptions &summary_options) {
|
2020-01-31 23:18:17 -08:00
|
|
|
return formatStringImpl<StringPrinter::StringElementType::ASCII>(
|
|
|
|
valobj, stream, summary_options, "");
|
2018-10-26 17:00:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool lldb_private::formatters::LibcxxStringSummaryProviderUTF16(
|
|
|
|
ValueObject &valobj, Stream &stream,
|
|
|
|
const TypeSummaryOptions &summary_options) {
|
2020-01-31 23:18:17 -08:00
|
|
|
return formatStringImpl<StringPrinter::StringElementType::UTF16>(
|
2018-10-26 17:00:48 +00:00
|
|
|
valobj, stream, summary_options, "u");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool lldb_private::formatters::LibcxxStringSummaryProviderUTF32(
|
|
|
|
ValueObject &valobj, Stream &stream,
|
|
|
|
const TypeSummaryOptions &summary_options) {
|
2020-01-31 23:18:17 -08:00
|
|
|
return formatStringImpl<StringPrinter::StringElementType::UTF32>(
|
2018-10-26 17:00:48 +00:00
|
|
|
valobj, stream, summary_options, "U");
|
|
|
|
}
|
2022-01-07 11:38:47 -08:00
|
|
|
|
|
|
|
static std::tuple<bool, ValueObjectSP, size_t>
|
|
|
|
LibcxxExtractStringViewData(ValueObject& valobj) {
|
2022-09-09 15:58:14 -07:00
|
|
|
auto dataobj = GetChildMemberWithName(
|
|
|
|
valobj, {ConstString("__data_"), ConstString("__data")});
|
|
|
|
auto sizeobj = GetChildMemberWithName(
|
|
|
|
valobj, {ConstString("__size_"), ConstString("__size")});
|
2022-01-07 11:38:47 -08:00
|
|
|
if (!dataobj || !sizeobj)
|
|
|
|
return std::make_tuple<bool,ValueObjectSP,size_t>(false, {}, {});
|
|
|
|
|
|
|
|
if (!dataobj->GetError().Success() || !sizeobj->GetError().Success())
|
|
|
|
return std::make_tuple<bool,ValueObjectSP,size_t>(false, {}, {});
|
|
|
|
|
|
|
|
bool success{false};
|
|
|
|
uint64_t size = sizeobj->GetValueAsUnsigned(0, &success);
|
|
|
|
if (!success)
|
|
|
|
return std::make_tuple<bool,ValueObjectSP,size_t>(false, {}, {});
|
|
|
|
|
|
|
|
return std::make_tuple(true,dataobj,size);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <StringPrinter::StringElementType element_type>
|
|
|
|
static bool formatStringViewImpl(ValueObject &valobj, Stream &stream,
|
|
|
|
const TypeSummaryOptions &summary_options,
|
|
|
|
std::string prefix_token) {
|
|
|
|
|
|
|
|
bool success;
|
|
|
|
ValueObjectSP dataobj;
|
|
|
|
size_t size;
|
|
|
|
std::tie(success, dataobj, size) = LibcxxExtractStringViewData(valobj);
|
|
|
|
|
|
|
|
if (!success) {
|
|
|
|
stream << "Summary Unavailable";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return LibcxxStringSummaryProvider<element_type>(
|
|
|
|
valobj, stream, summary_options, prefix_token, dataobj, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool lldb_private::formatters::LibcxxStringViewSummaryProviderASCII(
|
|
|
|
ValueObject &valobj, Stream &stream,
|
|
|
|
const TypeSummaryOptions &summary_options) {
|
|
|
|
return formatStringViewImpl<StringPrinter::StringElementType::ASCII>(
|
|
|
|
valobj, stream, summary_options, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool lldb_private::formatters::LibcxxStringViewSummaryProviderUTF16(
|
|
|
|
ValueObject &valobj, Stream &stream,
|
|
|
|
const TypeSummaryOptions &summary_options) {
|
|
|
|
return formatStringViewImpl<StringPrinter::StringElementType::UTF16>(
|
|
|
|
valobj, stream, summary_options, "u");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool lldb_private::formatters::LibcxxStringViewSummaryProviderUTF32(
|
|
|
|
ValueObject &valobj, Stream &stream,
|
|
|
|
const TypeSummaryOptions &summary_options) {
|
|
|
|
return formatStringViewImpl<StringPrinter::StringElementType::UTF32>(
|
|
|
|
valobj, stream, summary_options, "U");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool lldb_private::formatters::LibcxxWStringViewSummaryProvider(
|
|
|
|
ValueObject &valobj, Stream &stream,
|
|
|
|
const TypeSummaryOptions &summary_options) {
|
|
|
|
|
|
|
|
bool success;
|
|
|
|
ValueObjectSP dataobj;
|
|
|
|
size_t size;
|
|
|
|
std::tie( success, dataobj, size ) = LibcxxExtractStringViewData(valobj);
|
|
|
|
|
|
|
|
if (!success) {
|
|
|
|
stream << "Summary Unavailable";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return ::LibcxxWStringSummaryProvider(valobj, stream, summary_options,
|
|
|
|
dataobj, size);
|
|
|
|
}
|