Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
39642 views
//===-- BlockPointer.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 "BlockPointer.h"910#include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"11#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"12#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"13#include "lldb/Core/ValueObject.h"14#include "lldb/Core/ValueObjectConstResult.h"15#include "lldb/DataFormatters/FormattersHelpers.h"16#include "lldb/Symbol/CompilerType.h"17#include "lldb/Symbol/TypeSystem.h"18#include "lldb/Target/Target.h"19#include "lldb/Utility/LLDBAssert.h"20#include "lldb/Utility/LLDBLog.h"21#include "lldb/Utility/Log.h"2223using namespace lldb;24using namespace lldb_private;25using namespace lldb_private::formatters;2627namespace lldb_private {28namespace formatters {2930class BlockPointerSyntheticFrontEnd : public SyntheticChildrenFrontEnd {31public:32BlockPointerSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)33: SyntheticChildrenFrontEnd(*valobj_sp), m_block_struct_type() {34CompilerType block_pointer_type(m_backend.GetCompilerType());35CompilerType function_pointer_type;36block_pointer_type.IsBlockPointerType(&function_pointer_type);3738TargetSP target_sp(m_backend.GetTargetSP());3940if (!target_sp) {41return;42}4344auto type_system_or_err = target_sp->GetScratchTypeSystemForLanguage(45lldb::eLanguageTypeC_plus_plus);46if (auto err = type_system_or_err.takeError()) {47LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), std::move(err),48"Failed to get scratch TypeSystemClang: {0}");49return;50}5152auto ts = block_pointer_type.GetTypeSystem();53auto clang_ast_context = ts.dyn_cast_or_null<TypeSystemClang>();54if (!clang_ast_context)55return;5657const char *const isa_name("__isa");58const CompilerType isa_type =59clang_ast_context->GetBasicType(lldb::eBasicTypeObjCClass);60const char *const flags_name("__flags");61const CompilerType flags_type =62clang_ast_context->GetBasicType(lldb::eBasicTypeInt);63const char *const reserved_name("__reserved");64const CompilerType reserved_type =65clang_ast_context->GetBasicType(lldb::eBasicTypeInt);66const char *const FuncPtr_name("__FuncPtr");6768m_block_struct_type = clang_ast_context->CreateStructForIdentifier(69llvm::StringRef(), {{isa_name, isa_type},70{flags_name, flags_type},71{reserved_name, reserved_type},72{FuncPtr_name, function_pointer_type}});73}7475~BlockPointerSyntheticFrontEnd() override = default;7677llvm::Expected<uint32_t> CalculateNumChildren() override {78const bool omit_empty_base_classes = false;79return m_block_struct_type.GetNumChildren(omit_empty_base_classes, nullptr);80}8182lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override {83if (!m_block_struct_type.IsValid()) {84return lldb::ValueObjectSP();85}8687if (idx >= CalculateNumChildrenIgnoringErrors()) {88return lldb::ValueObjectSP();89}9091const bool thread_and_frame_only_if_stopped = true;92ExecutionContext exe_ctx = m_backend.GetExecutionContextRef().Lock(93thread_and_frame_only_if_stopped);94const bool transparent_pointers = false;95const bool omit_empty_base_classes = false;96const bool ignore_array_bounds = false;97ValueObject *value_object = nullptr;9899std::string child_name;100uint32_t child_byte_size = 0;101int32_t child_byte_offset = 0;102uint32_t child_bitfield_bit_size = 0;103uint32_t child_bitfield_bit_offset = 0;104bool child_is_base_class = false;105bool child_is_deref_of_parent = false;106uint64_t language_flags = 0;107108auto child_type_or_err = m_block_struct_type.GetChildCompilerTypeAtIndex(109&exe_ctx, idx, transparent_pointers, omit_empty_base_classes,110ignore_array_bounds, child_name, child_byte_size, child_byte_offset,111child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,112child_is_deref_of_parent, value_object, language_flags);113if (!child_type_or_err)114return ValueObjectConstResult::Create(115exe_ctx.GetBestExecutionContextScope(),116Status(child_type_or_err.takeError()));117CompilerType child_type = *child_type_or_err;118119ValueObjectSP struct_pointer_sp =120m_backend.Cast(m_block_struct_type.GetPointerType());121122if (!struct_pointer_sp) {123return lldb::ValueObjectSP();124}125126Status err;127ValueObjectSP struct_sp = struct_pointer_sp->Dereference(err);128129if (!struct_sp || !err.Success()) {130return lldb::ValueObjectSP();131}132133ValueObjectSP child_sp(struct_sp->GetSyntheticChildAtOffset(134child_byte_offset, child_type, true,135ConstString(child_name.c_str(), child_name.size())));136137return child_sp;138}139140// return true if this object is now safe to use forever without ever141// updating again; the typical (and tested) answer here is 'false'142lldb::ChildCacheState Update() override {143return lldb::ChildCacheState::eRefetch;144}145146// maybe return false if the block pointer is, say, null147bool MightHaveChildren() override { return true; }148149size_t GetIndexOfChildWithName(ConstString name) override {150if (!m_block_struct_type.IsValid())151return UINT32_MAX;152153const bool omit_empty_base_classes = false;154return m_block_struct_type.GetIndexOfChildWithName(name.AsCString(),155omit_empty_base_classes);156}157158private:159CompilerType m_block_struct_type;160};161162} // namespace formatters163} // namespace lldb_private164165bool lldb_private::formatters::BlockPointerSummaryProvider(166ValueObject &valobj, Stream &s, const TypeSummaryOptions &) {167lldb_private::SyntheticChildrenFrontEnd *synthetic_children =168BlockPointerSyntheticFrontEndCreator(nullptr, valobj.GetSP());169if (!synthetic_children) {170return false;171}172173synthetic_children->Update();174175static const ConstString s_FuncPtr_name("__FuncPtr");176177lldb::ValueObjectSP child_sp = synthetic_children->GetChildAtIndex(178synthetic_children->GetIndexOfChildWithName(s_FuncPtr_name));179180if (!child_sp) {181return false;182}183184lldb::ValueObjectSP qualified_child_representation_sp =185child_sp->GetQualifiedRepresentationIfAvailable(186lldb::eDynamicDontRunTarget, true);187188const char *child_value =189qualified_child_representation_sp->GetValueAsCString();190191s.Printf("%s", child_value);192193return true;194}195196lldb_private::SyntheticChildrenFrontEnd *197lldb_private::formatters::BlockPointerSyntheticFrontEndCreator(198CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {199if (!valobj_sp)200return nullptr;201return new BlockPointerSyntheticFrontEnd(valobj_sp);202}203204205