Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp
39642 views
//===-- LibCxxVector.cpp --------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "LibCxx.h"910#include "lldb/Core/ValueObject.h"11#include "lldb/DataFormatters/FormattersHelpers.h"12#include "lldb/Utility/ConstString.h"13#include <optional>1415using namespace lldb;16using namespace lldb_private;17using namespace lldb_private::formatters;1819namespace lldb_private {20namespace formatters {21class LibcxxStdVectorSyntheticFrontEnd : public SyntheticChildrenFrontEnd {22public:23LibcxxStdVectorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);2425~LibcxxStdVectorSyntheticFrontEnd() override;2627llvm::Expected<uint32_t> CalculateNumChildren() override;2829lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;3031lldb::ChildCacheState Update() override;3233bool MightHaveChildren() override;3435size_t GetIndexOfChildWithName(ConstString name) override;3637private:38ValueObject *m_start = nullptr;39ValueObject *m_finish = nullptr;40CompilerType m_element_type;41uint32_t m_element_size = 0;42};4344class LibcxxVectorBoolSyntheticFrontEnd : public SyntheticChildrenFrontEnd {45public:46LibcxxVectorBoolSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);4748llvm::Expected<uint32_t> CalculateNumChildren() override;4950lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;5152lldb::ChildCacheState Update() override;5354bool MightHaveChildren() override { return true; }5556size_t GetIndexOfChildWithName(ConstString name) override;5758private:59CompilerType m_bool_type;60ExecutionContextRef m_exe_ctx_ref;61uint64_t m_count = 0;62lldb::addr_t m_base_data_address = 0;63std::map<size_t, lldb::ValueObjectSP> m_children;64};6566} // namespace formatters67} // namespace lldb_private6869lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::70LibcxxStdVectorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)71: SyntheticChildrenFrontEnd(*valobj_sp), m_element_type() {72if (valobj_sp)73Update();74}7576lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::77~LibcxxStdVectorSyntheticFrontEnd() {78// these need to stay around because they are child objects who will follow79// their parent's life cycle80// delete m_start;81// delete m_finish;82}8384llvm::Expected<uint32_t> lldb_private::formatters::85LibcxxStdVectorSyntheticFrontEnd::CalculateNumChildren() {86if (!m_start || !m_finish)87return 0;88uint64_t start_val = m_start->GetValueAsUnsigned(0);89uint64_t finish_val = m_finish->GetValueAsUnsigned(0);9091if (start_val == 0 || finish_val == 0)92return 0;9394if (start_val >= finish_val)95return 0;9697size_t num_children = (finish_val - start_val);98if (num_children % m_element_size)99return 0;100return num_children / m_element_size;101}102103lldb::ValueObjectSP104lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetChildAtIndex(105uint32_t idx) {106if (!m_start || !m_finish)107return lldb::ValueObjectSP();108109uint64_t offset = idx * m_element_size;110offset = offset + m_start->GetValueAsUnsigned(0);111StreamString name;112name.Printf("[%" PRIu64 "]", (uint64_t)idx);113return CreateValueObjectFromAddress(name.GetString(), offset,114m_backend.GetExecutionContextRef(),115m_element_type);116}117118lldb::ChildCacheState119lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update() {120m_start = m_finish = nullptr;121ValueObjectSP data_type_finder_sp(122m_backend.GetChildMemberWithName("__end_cap_"));123if (!data_type_finder_sp)124return lldb::ChildCacheState::eRefetch;125126data_type_finder_sp =127GetFirstValueOfLibCXXCompressedPair(*data_type_finder_sp);128if (!data_type_finder_sp)129return lldb::ChildCacheState::eRefetch;130131m_element_type = data_type_finder_sp->GetCompilerType().GetPointeeType();132if (std::optional<uint64_t> size = m_element_type.GetByteSize(nullptr)) {133m_element_size = *size;134135if (m_element_size > 0) {136// store raw pointers or end up with a circular dependency137m_start = m_backend.GetChildMemberWithName("__begin_").get();138m_finish = m_backend.GetChildMemberWithName("__end_").get();139}140}141return lldb::ChildCacheState::eRefetch;142}143144bool lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::145MightHaveChildren() {146return true;147}148149size_t lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::150GetIndexOfChildWithName(ConstString name) {151if (!m_start || !m_finish)152return UINT32_MAX;153return ExtractIndexFromString(name.GetCString());154}155156lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::157LibcxxVectorBoolSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)158: SyntheticChildrenFrontEnd(*valobj_sp), m_bool_type(), m_exe_ctx_ref(),159m_children() {160if (valobj_sp) {161Update();162m_bool_type =163valobj_sp->GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeBool);164}165}166167llvm::Expected<uint32_t> lldb_private::formatters::168LibcxxVectorBoolSyntheticFrontEnd::CalculateNumChildren() {169return m_count;170}171172lldb::ValueObjectSP173lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex(174uint32_t idx) {175auto iter = m_children.find(idx), end = m_children.end();176if (iter != end)177return iter->second;178if (idx >= m_count)179return {};180if (m_base_data_address == 0 || m_count == 0)181return {};182if (!m_bool_type)183return {};184size_t byte_idx = (idx >> 3); // divide by 8 to get byte index185size_t bit_index = (idx & 7); // efficient idx % 8 for bit index186lldb::addr_t byte_location = m_base_data_address + byte_idx;187ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());188if (!process_sp)189return {};190uint8_t byte = 0;191uint8_t mask = 0;192Status err;193size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err);194if (err.Fail() || bytes_read == 0)195return {};196mask = 1 << bit_index;197bool bit_set = ((byte & mask) != 0);198std::optional<uint64_t> size = m_bool_type.GetByteSize(nullptr);199if (!size)200return {};201WritableDataBufferSP buffer_sp(new DataBufferHeap(*size, 0));202if (bit_set && buffer_sp && buffer_sp->GetBytes()) {203// regardless of endianness, anything non-zero is true204*(buffer_sp->GetBytes()) = 1;205}206StreamString name;207name.Printf("[%" PRIu64 "]", (uint64_t)idx);208ValueObjectSP retval_sp(CreateValueObjectFromData(209name.GetString(),210DataExtractor(buffer_sp, process_sp->GetByteOrder(),211process_sp->GetAddressByteSize()),212m_exe_ctx_ref, m_bool_type));213if (retval_sp)214m_children[idx] = retval_sp;215return retval_sp;216}217218/*(std::__1::vector<std::__1::allocator<bool> >) vBool = {219__begin_ = 0x00000001001000e0220__size_ = 56221__cap_alloc_ = {222std::__1::__libcpp_compressed_pair_imp<unsigned long,223std::__1::allocator<unsigned long> > = {224__first_ = 1225}226}227}*/228229lldb::ChildCacheState230lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::Update() {231m_children.clear();232ValueObjectSP valobj_sp = m_backend.GetSP();233if (!valobj_sp)234return lldb::ChildCacheState::eRefetch;235m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();236ValueObjectSP size_sp(valobj_sp->GetChildMemberWithName("__size_"));237if (!size_sp)238return lldb::ChildCacheState::eRefetch;239m_count = size_sp->GetValueAsUnsigned(0);240if (!m_count)241return lldb::ChildCacheState::eReuse;242ValueObjectSP begin_sp(valobj_sp->GetChildMemberWithName("__begin_"));243if (!begin_sp) {244m_count = 0;245return lldb::ChildCacheState::eRefetch;246}247m_base_data_address = begin_sp->GetValueAsUnsigned(0);248if (!m_base_data_address) {249m_count = 0;250return lldb::ChildCacheState::eRefetch;251}252return lldb::ChildCacheState::eRefetch;253}254255size_t lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::256GetIndexOfChildWithName(ConstString name) {257if (!m_count || !m_base_data_address)258return UINT32_MAX;259const char *item_name = name.GetCString();260uint32_t idx = ExtractIndexFromString(item_name);261if (idx < UINT32_MAX && idx >= CalculateNumChildrenIgnoringErrors())262return UINT32_MAX;263return idx;264}265266lldb_private::SyntheticChildrenFrontEnd *267lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator(268CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {269if (!valobj_sp)270return nullptr;271CompilerType type = valobj_sp->GetCompilerType();272if (!type.IsValid() || type.GetNumTemplateArguments() == 0)273return nullptr;274CompilerType arg_type = type.GetTypeTemplateArgument(0);275if (arg_type.GetTypeName() == "bool")276return new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp);277return new LibcxxStdVectorSyntheticFrontEnd(valobj_sp);278}279280281