brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.1 KiB · 9ab1bf0 Raw
211 lines · cpp
1//===-- BlockPointer.cpp --------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "BlockPointer.h"10 11#include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"12#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"13#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"14#include "lldb/DataFormatters/FormattersHelpers.h"15#include "lldb/Symbol/CompilerType.h"16#include "lldb/Symbol/TypeSystem.h"17#include "lldb/Target/Target.h"18#include "lldb/Utility/LLDBAssert.h"19#include "lldb/Utility/LLDBLog.h"20#include "lldb/Utility/Log.h"21#include "lldb/ValueObject/ValueObject.h"22#include "lldb/ValueObject/ValueObjectConstResult.h"23 24using namespace lldb;25using namespace lldb_private;26using namespace lldb_private::formatters;27 28namespace lldb_private {29namespace formatters {30 31class BlockPointerSyntheticFrontEnd : public SyntheticChildrenFrontEnd {32public:33  BlockPointerSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)34      : SyntheticChildrenFrontEnd(*valobj_sp), m_block_struct_type() {35    CompilerType block_pointer_type(m_backend.GetCompilerType());36    CompilerType function_pointer_type;37    block_pointer_type.IsBlockPointerType(&function_pointer_type);38 39    TargetSP target_sp(m_backend.GetTargetSP());40 41    if (!target_sp) {42      return;43    }44 45    auto type_system_or_err = target_sp->GetScratchTypeSystemForLanguage(46        lldb::eLanguageTypeC_plus_plus);47    if (auto err = type_system_or_err.takeError()) {48      LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), std::move(err),49                     "Failed to get scratch TypeSystemClang: {0}");50      return;51    }52 53    auto clang_ast_context =54        block_pointer_type.GetTypeSystem<TypeSystemClang>();55    if (!clang_ast_context)56      return;57 58    const char *const isa_name("__isa");59    const CompilerType isa_type =60        clang_ast_context->GetBasicType(lldb::eBasicTypeObjCClass);61    const char *const flags_name("__flags");62    const CompilerType flags_type =63        clang_ast_context->GetBasicType(lldb::eBasicTypeInt);64    const char *const reserved_name("__reserved");65    const CompilerType reserved_type =66        clang_ast_context->GetBasicType(lldb::eBasicTypeInt);67    const char *const FuncPtr_name("__FuncPtr");68 69    m_block_struct_type = clang_ast_context->CreateStructForIdentifier(70        llvm::StringRef(), {{isa_name, isa_type},71                            {flags_name, flags_type},72                            {reserved_name, reserved_type},73                            {FuncPtr_name, function_pointer_type}});74  }75 76  ~BlockPointerSyntheticFrontEnd() override = default;77 78  llvm::Expected<uint32_t> CalculateNumChildren() override {79    const bool omit_empty_base_classes = false;80    return m_block_struct_type.GetNumChildren(omit_empty_base_classes, nullptr);81  }82 83  lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override {84    if (!m_block_struct_type.IsValid()) {85      return lldb::ValueObjectSP();86    }87 88    if (idx >= CalculateNumChildrenIgnoringErrors()) {89      return lldb::ValueObjectSP();90    }91 92    const bool thread_and_frame_only_if_stopped = true;93    ExecutionContext exe_ctx = m_backend.GetExecutionContextRef().Lock(94        thread_and_frame_only_if_stopped);95    const bool transparent_pointers = false;96    const bool omit_empty_base_classes = false;97    const bool ignore_array_bounds = false;98    ValueObject *value_object = nullptr;99 100    std::string child_name;101    uint32_t child_byte_size = 0;102    int32_t child_byte_offset = 0;103    uint32_t child_bitfield_bit_size = 0;104    uint32_t child_bitfield_bit_offset = 0;105    bool child_is_base_class = false;106    bool child_is_deref_of_parent = false;107    uint64_t language_flags = 0;108 109    auto child_type_or_err = m_block_struct_type.GetChildCompilerTypeAtIndex(110        &exe_ctx, idx, transparent_pointers, omit_empty_base_classes,111        ignore_array_bounds, child_name, child_byte_size, child_byte_offset,112        child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,113        child_is_deref_of_parent, value_object, language_flags);114    if (!child_type_or_err)115      return ValueObjectConstResult::Create(116          exe_ctx.GetBestExecutionContextScope(),117          Status::FromError(child_type_or_err.takeError()));118    CompilerType child_type = *child_type_or_err;119 120    ValueObjectSP struct_pointer_sp =121        m_backend.Cast(m_block_struct_type.GetPointerType());122 123    if (!struct_pointer_sp) {124      return lldb::ValueObjectSP();125    }126 127    Status err;128    ValueObjectSP struct_sp = struct_pointer_sp->Dereference(err);129 130    if (!struct_sp || !err.Success()) {131      return lldb::ValueObjectSP();132    }133 134    ValueObjectSP child_sp(struct_sp->GetSyntheticChildAtOffset(135        child_byte_offset, child_type, true,136        ConstString(child_name.c_str(), child_name.size())));137 138    return child_sp;139  }140 141  // return true if this object is now safe to use forever without ever142  // updating again; the typical (and tested) answer here is 'false'143  lldb::ChildCacheState Update() override {144    return lldb::ChildCacheState::eRefetch;145  }146 147  llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override {148    if (!m_block_struct_type.IsValid())149      return llvm::createStringError("Type has no child named '%s'",150                                     name.AsCString());151 152    const bool omit_empty_base_classes = false;153    return m_block_struct_type.GetIndexOfChildWithName(name.AsCString(),154                                                       omit_empty_base_classes);155  }156 157private:158  CompilerType m_block_struct_type;159};160 161} // namespace formatters162} // namespace lldb_private163 164bool lldb_private::formatters::BlockPointerSummaryProvider(165    ValueObject &valobj, Stream &s, const TypeSummaryOptions &) {166  lldb_private::SyntheticChildrenFrontEnd *synthetic_children =167      BlockPointerSyntheticFrontEndCreator(nullptr, valobj.GetSP());168  if (!synthetic_children) {169    return false;170  }171 172  synthetic_children->Update();173 174  static const ConstString s_FuncPtr_name("__FuncPtr");175 176  auto index_or_err =177      synthetic_children->GetIndexOfChildWithName(s_FuncPtr_name);178 179  if (!index_or_err) {180    LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), index_or_err.takeError(),181                   "{0}");182    return false;183  }184 185  lldb::ValueObjectSP child_sp =186      synthetic_children->GetChildAtIndex(*index_or_err);187 188  if (!child_sp) {189    return false;190  }191 192  lldb::ValueObjectSP qualified_child_representation_sp =193      child_sp->GetQualifiedRepresentationIfAvailable(194          lldb::eDynamicDontRunTarget, true);195 196  const char *child_value =197      qualified_child_representation_sp->GetValueAsCString();198 199  s.Printf("%s", child_value);200 201  return true;202}203 204lldb_private::SyntheticChildrenFrontEnd *205lldb_private::formatters::BlockPointerSyntheticFrontEndCreator(206    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {207  if (!valobj_sp)208    return nullptr;209  return new BlockPointerSyntheticFrontEnd(valobj_sp);210}211