xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
15ffd83dbSDimitry Andric //===-- BlockPointer.cpp --------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "BlockPointer.h"
100b57cec5SDimitry Andric 
115ffd83dbSDimitry Andric #include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"
125ffd83dbSDimitry Andric #include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
135ffd83dbSDimitry Andric #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
140b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h"
15*0fca6ea1SDimitry Andric #include "lldb/Core/ValueObjectConstResult.h"
160b57cec5SDimitry Andric #include "lldb/DataFormatters/FormattersHelpers.h"
170b57cec5SDimitry Andric #include "lldb/Symbol/CompilerType.h"
180b57cec5SDimitry Andric #include "lldb/Symbol/TypeSystem.h"
190b57cec5SDimitry Andric #include "lldb/Target/Target.h"
200b57cec5SDimitry Andric #include "lldb/Utility/LLDBAssert.h"
2181ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
229dba64beSDimitry Andric #include "lldb/Utility/Log.h"
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric using namespace lldb;
250b57cec5SDimitry Andric using namespace lldb_private;
260b57cec5SDimitry Andric using namespace lldb_private::formatters;
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric namespace lldb_private {
290b57cec5SDimitry Andric namespace formatters {
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric class BlockPointerSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
320b57cec5SDimitry Andric public:
330b57cec5SDimitry Andric   BlockPointerSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
340b57cec5SDimitry Andric       : SyntheticChildrenFrontEnd(*valobj_sp), m_block_struct_type() {
350b57cec5SDimitry Andric     CompilerType block_pointer_type(m_backend.GetCompilerType());
360b57cec5SDimitry Andric     CompilerType function_pointer_type;
370b57cec5SDimitry Andric     block_pointer_type.IsBlockPointerType(&function_pointer_type);
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric     TargetSP target_sp(m_backend.GetTargetSP());
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric     if (!target_sp) {
420b57cec5SDimitry Andric       return;
430b57cec5SDimitry Andric     }
440b57cec5SDimitry Andric 
459dba64beSDimitry Andric     auto type_system_or_err = target_sp->GetScratchTypeSystemForLanguage(
469dba64beSDimitry Andric         lldb::eLanguageTypeC_plus_plus);
479dba64beSDimitry Andric     if (auto err = type_system_or_err.takeError()) {
4881ad6265SDimitry Andric       LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), std::move(err),
4906c3fb27SDimitry Andric                      "Failed to get scratch TypeSystemClang: {0}");
500b57cec5SDimitry Andric       return;
510b57cec5SDimitry Andric     }
520b57cec5SDimitry Andric 
53bdd1243dSDimitry Andric     auto ts = block_pointer_type.GetTypeSystem();
54bdd1243dSDimitry Andric     auto clang_ast_context = ts.dyn_cast_or_null<TypeSystemClang>();
55bdd1243dSDimitry Andric     if (!clang_ast_context)
56bdd1243dSDimitry Andric       return;
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric     const char *const isa_name("__isa");
590b57cec5SDimitry Andric     const CompilerType isa_type =
600b57cec5SDimitry Andric         clang_ast_context->GetBasicType(lldb::eBasicTypeObjCClass);
610b57cec5SDimitry Andric     const char *const flags_name("__flags");
620b57cec5SDimitry Andric     const CompilerType flags_type =
630b57cec5SDimitry Andric         clang_ast_context->GetBasicType(lldb::eBasicTypeInt);
640b57cec5SDimitry Andric     const char *const reserved_name("__reserved");
650b57cec5SDimitry Andric     const CompilerType reserved_type =
660b57cec5SDimitry Andric         clang_ast_context->GetBasicType(lldb::eBasicTypeInt);
670b57cec5SDimitry Andric     const char *const FuncPtr_name("__FuncPtr");
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric     m_block_struct_type = clang_ast_context->CreateStructForIdentifier(
7006c3fb27SDimitry Andric         llvm::StringRef(), {{isa_name, isa_type},
710b57cec5SDimitry Andric                             {flags_name, flags_type},
720b57cec5SDimitry Andric                             {reserved_name, reserved_type},
73fe6060f1SDimitry Andric                             {FuncPtr_name, function_pointer_type}});
740b57cec5SDimitry Andric   }
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   ~BlockPointerSyntheticFrontEnd() override = default;
770b57cec5SDimitry Andric 
78*0fca6ea1SDimitry Andric   llvm::Expected<uint32_t> CalculateNumChildren() override {
790b57cec5SDimitry Andric     const bool omit_empty_base_classes = false;
800b57cec5SDimitry Andric     return m_block_struct_type.GetNumChildren(omit_empty_base_classes, nullptr);
810b57cec5SDimitry Andric   }
820b57cec5SDimitry Andric 
83*0fca6ea1SDimitry Andric   lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override {
840b57cec5SDimitry Andric     if (!m_block_struct_type.IsValid()) {
850b57cec5SDimitry Andric       return lldb::ValueObjectSP();
860b57cec5SDimitry Andric     }
870b57cec5SDimitry Andric 
88*0fca6ea1SDimitry Andric     if (idx >= CalculateNumChildrenIgnoringErrors()) {
890b57cec5SDimitry Andric       return lldb::ValueObjectSP();
900b57cec5SDimitry Andric     }
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric     const bool thread_and_frame_only_if_stopped = true;
930b57cec5SDimitry Andric     ExecutionContext exe_ctx = m_backend.GetExecutionContextRef().Lock(
940b57cec5SDimitry Andric         thread_and_frame_only_if_stopped);
950b57cec5SDimitry Andric     const bool transparent_pointers = false;
960b57cec5SDimitry Andric     const bool omit_empty_base_classes = false;
970b57cec5SDimitry Andric     const bool ignore_array_bounds = false;
980b57cec5SDimitry Andric     ValueObject *value_object = nullptr;
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric     std::string child_name;
1010b57cec5SDimitry Andric     uint32_t child_byte_size = 0;
1020b57cec5SDimitry Andric     int32_t child_byte_offset = 0;
1030b57cec5SDimitry Andric     uint32_t child_bitfield_bit_size = 0;
1040b57cec5SDimitry Andric     uint32_t child_bitfield_bit_offset = 0;
1050b57cec5SDimitry Andric     bool child_is_base_class = false;
1060b57cec5SDimitry Andric     bool child_is_deref_of_parent = false;
1070b57cec5SDimitry Andric     uint64_t language_flags = 0;
1080b57cec5SDimitry Andric 
109*0fca6ea1SDimitry Andric     auto child_type_or_err = m_block_struct_type.GetChildCompilerTypeAtIndex(
1100b57cec5SDimitry Andric         &exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
1110b57cec5SDimitry Andric         ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
112*0fca6ea1SDimitry Andric         child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,
113*0fca6ea1SDimitry Andric         child_is_deref_of_parent, value_object, language_flags);
114*0fca6ea1SDimitry Andric     if (!child_type_or_err)
115*0fca6ea1SDimitry Andric       return ValueObjectConstResult::Create(
116*0fca6ea1SDimitry Andric           exe_ctx.GetBestExecutionContextScope(),
117*0fca6ea1SDimitry Andric           Status(child_type_or_err.takeError()));
118*0fca6ea1SDimitry Andric     CompilerType child_type = *child_type_or_err;
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric     ValueObjectSP struct_pointer_sp =
1210b57cec5SDimitry Andric         m_backend.Cast(m_block_struct_type.GetPointerType());
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric     if (!struct_pointer_sp) {
1240b57cec5SDimitry Andric       return lldb::ValueObjectSP();
1250b57cec5SDimitry Andric     }
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric     Status err;
1280b57cec5SDimitry Andric     ValueObjectSP struct_sp = struct_pointer_sp->Dereference(err);
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric     if (!struct_sp || !err.Success()) {
1310b57cec5SDimitry Andric       return lldb::ValueObjectSP();
1320b57cec5SDimitry Andric     }
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric     ValueObjectSP child_sp(struct_sp->GetSyntheticChildAtOffset(
1350b57cec5SDimitry Andric         child_byte_offset, child_type, true,
1360b57cec5SDimitry Andric         ConstString(child_name.c_str(), child_name.size())));
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric     return child_sp;
1390b57cec5SDimitry Andric   }
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   // return true if this object is now safe to use forever without ever
1420b57cec5SDimitry Andric   // updating again; the typical (and tested) answer here is 'false'
143*0fca6ea1SDimitry Andric   lldb::ChildCacheState Update() override {
144*0fca6ea1SDimitry Andric     return lldb::ChildCacheState::eRefetch;
145*0fca6ea1SDimitry Andric   }
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric   // maybe return false if the block pointer is, say, null
1480b57cec5SDimitry Andric   bool MightHaveChildren() override { return true; }
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric   size_t GetIndexOfChildWithName(ConstString name) override {
1510b57cec5SDimitry Andric     if (!m_block_struct_type.IsValid())
1520b57cec5SDimitry Andric       return UINT32_MAX;
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric     const bool omit_empty_base_classes = false;
1550b57cec5SDimitry Andric     return m_block_struct_type.GetIndexOfChildWithName(name.AsCString(),
1560b57cec5SDimitry Andric                                                        omit_empty_base_classes);
1570b57cec5SDimitry Andric   }
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric private:
1600b57cec5SDimitry Andric   CompilerType m_block_struct_type;
1610b57cec5SDimitry Andric };
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric } // namespace formatters
1640b57cec5SDimitry Andric } // namespace lldb_private
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric bool lldb_private::formatters::BlockPointerSummaryProvider(
1670b57cec5SDimitry Andric     ValueObject &valobj, Stream &s, const TypeSummaryOptions &) {
1680b57cec5SDimitry Andric   lldb_private::SyntheticChildrenFrontEnd *synthetic_children =
1690b57cec5SDimitry Andric       BlockPointerSyntheticFrontEndCreator(nullptr, valobj.GetSP());
1700b57cec5SDimitry Andric   if (!synthetic_children) {
1710b57cec5SDimitry Andric     return false;
1720b57cec5SDimitry Andric   }
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric   synthetic_children->Update();
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric   static const ConstString s_FuncPtr_name("__FuncPtr");
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric   lldb::ValueObjectSP child_sp = synthetic_children->GetChildAtIndex(
1790b57cec5SDimitry Andric       synthetic_children->GetIndexOfChildWithName(s_FuncPtr_name));
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric   if (!child_sp) {
1820b57cec5SDimitry Andric     return false;
1830b57cec5SDimitry Andric   }
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric   lldb::ValueObjectSP qualified_child_representation_sp =
1860b57cec5SDimitry Andric       child_sp->GetQualifiedRepresentationIfAvailable(
1870b57cec5SDimitry Andric           lldb::eDynamicDontRunTarget, true);
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   const char *child_value =
1900b57cec5SDimitry Andric       qualified_child_representation_sp->GetValueAsCString();
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric   s.Printf("%s", child_value);
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric   return true;
1950b57cec5SDimitry Andric }
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric lldb_private::SyntheticChildrenFrontEnd *
1980b57cec5SDimitry Andric lldb_private::formatters::BlockPointerSyntheticFrontEndCreator(
1990b57cec5SDimitry Andric     CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
2000b57cec5SDimitry Andric   if (!valobj_sp)
2010b57cec5SDimitry Andric     return nullptr;
2020b57cec5SDimitry Andric   return new BlockPointerSyntheticFrontEnd(valobj_sp);
2030b57cec5SDimitry Andric }
204