LLDB  mainline
BlockPointer.cpp
Go to the documentation of this file.
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "BlockPointer.h"
10 
14 #include "lldb/Core/ValueObject.h"
17 #include "lldb/Symbol/TypeSystem.h"
18 #include "lldb/Target/Target.h"
20 #include "lldb/Utility/Log.h"
21 
22 using namespace lldb;
23 using namespace lldb_private;
24 using namespace lldb_private::formatters;
25 
26 namespace lldb_private {
27 namespace formatters {
28 
30 public:
31  BlockPointerSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
32  : SyntheticChildrenFrontEnd(*valobj_sp), m_block_struct_type() {
33  CompilerType block_pointer_type(m_backend.GetCompilerType());
34  CompilerType function_pointer_type;
35  block_pointer_type.IsBlockPointerType(&function_pointer_type);
36 
37  TargetSP target_sp(m_backend.GetTargetSP());
38 
39  if (!target_sp) {
40  return;
41  }
42 
43  auto type_system_or_err = target_sp->GetScratchTypeSystemForLanguage(
45  if (auto err = type_system_or_err.takeError()) {
48  std::move(err), "Failed to get scratch TypeSystemClang");
49  return;
50  }
51 
52  TypeSystemClang *clang_ast_context =
53  llvm::dyn_cast<TypeSystemClang>(&type_system_or_err.get());
54 
55  if (!clang_ast_context) {
56  return;
57  }
58 
59  std::shared_ptr<ClangASTImporter> clang_ast_importer;
60  auto *state = target_sp->GetPersistentExpressionStateForLanguage(
62  if (state) {
63  auto *persistent_vars = llvm::cast<ClangPersistentVariables>(state);
64  clang_ast_importer = persistent_vars->GetClangASTImporter();
65  }
66 
67  if (!clang_ast_importer) {
68  return;
69  }
70 
71  const char *const isa_name("__isa");
72  const CompilerType isa_type =
73  clang_ast_context->GetBasicType(lldb::eBasicTypeObjCClass);
74  const char *const flags_name("__flags");
75  const CompilerType flags_type =
76  clang_ast_context->GetBasicType(lldb::eBasicTypeInt);
77  const char *const reserved_name("__reserved");
78  const CompilerType reserved_type =
79  clang_ast_context->GetBasicType(lldb::eBasicTypeInt);
80  const char *const FuncPtr_name("__FuncPtr");
81  const CompilerType FuncPtr_type =
82  clang_ast_importer->CopyType(*clang_ast_context, function_pointer_type);
83 
84  m_block_struct_type = clang_ast_context->CreateStructForIdentifier(
85  ConstString(), {{isa_name, isa_type},
86  {flags_name, flags_type},
87  {reserved_name, reserved_type},
88  {FuncPtr_name, FuncPtr_type}});
89  }
90 
91  ~BlockPointerSyntheticFrontEnd() override = default;
92 
93  size_t CalculateNumChildren() override {
94  const bool omit_empty_base_classes = false;
95  return m_block_struct_type.GetNumChildren(omit_empty_base_classes, nullptr);
96  }
97 
98  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
99  if (!m_block_struct_type.IsValid()) {
100  return lldb::ValueObjectSP();
101  }
102 
103  if (idx >= CalculateNumChildren()) {
104  return lldb::ValueObjectSP();
105  }
106 
107  const bool thread_and_frame_only_if_stopped = true;
108  ExecutionContext exe_ctx = m_backend.GetExecutionContextRef().Lock(
109  thread_and_frame_only_if_stopped);
110  const bool transparent_pointers = false;
111  const bool omit_empty_base_classes = false;
112  const bool ignore_array_bounds = false;
113  ValueObject *value_object = nullptr;
114 
115  std::string child_name;
116  uint32_t child_byte_size = 0;
117  int32_t child_byte_offset = 0;
118  uint32_t child_bitfield_bit_size = 0;
119  uint32_t child_bitfield_bit_offset = 0;
120  bool child_is_base_class = false;
121  bool child_is_deref_of_parent = false;
122  uint64_t language_flags = 0;
123 
124  const CompilerType child_type =
125  m_block_struct_type.GetChildCompilerTypeAtIndex(
126  &exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
127  ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
128  child_bitfield_bit_size, child_bitfield_bit_offset,
129  child_is_base_class, child_is_deref_of_parent, value_object,
130  language_flags);
131 
132  ValueObjectSP struct_pointer_sp =
133  m_backend.Cast(m_block_struct_type.GetPointerType());
134 
135  if (!struct_pointer_sp) {
136  return lldb::ValueObjectSP();
137  }
138 
139  Status err;
140  ValueObjectSP struct_sp = struct_pointer_sp->Dereference(err);
141 
142  if (!struct_sp || !err.Success()) {
143  return lldb::ValueObjectSP();
144  }
145 
146  ValueObjectSP child_sp(struct_sp->GetSyntheticChildAtOffset(
147  child_byte_offset, child_type, true,
148  ConstString(child_name.c_str(), child_name.size())));
149 
150  return child_sp;
151  }
152 
153  // return true if this object is now safe to use forever without ever
154  // updating again; the typical (and tested) answer here is 'false'
155  bool Update() override { return false; }
156 
157  // maybe return false if the block pointer is, say, null
158  bool MightHaveChildren() override { return true; }
159 
160  size_t GetIndexOfChildWithName(ConstString name) override {
161  if (!m_block_struct_type.IsValid())
162  return UINT32_MAX;
163 
164  const bool omit_empty_base_classes = false;
165  return m_block_struct_type.GetIndexOfChildWithName(name.AsCString(),
166  omit_empty_base_classes);
167  }
168 
169 private:
171 };
172 
173 } // namespace formatters
174 } // namespace lldb_private
175 
177  ValueObject &valobj, Stream &s, const TypeSummaryOptions &) {
178  lldb_private::SyntheticChildrenFrontEnd *synthetic_children =
179  BlockPointerSyntheticFrontEndCreator(nullptr, valobj.GetSP());
180  if (!synthetic_children) {
181  return false;
182  }
183 
184  synthetic_children->Update();
185 
186  static const ConstString s_FuncPtr_name("__FuncPtr");
187 
188  lldb::ValueObjectSP child_sp = synthetic_children->GetChildAtIndex(
189  synthetic_children->GetIndexOfChildWithName(s_FuncPtr_name));
190 
191  if (!child_sp) {
192  return false;
193  }
194 
195  lldb::ValueObjectSP qualified_child_representation_sp =
196  child_sp->GetQualifiedRepresentationIfAvailable(
198 
199  const char *child_value =
200  qualified_child_representation_sp->GetValueAsCString();
201 
202  s.Printf("%s", child_value);
203 
204  return true;
205 }
206 
209  CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
210  if (!valobj_sp)
211  return nullptr;
212  return new BlockPointerSyntheticFrontEnd(valobj_sp);
213 }
bool BlockPointerSummaryProvider(ValueObject &, Stream &, const TypeSummaryOptions &)
#define LIBLLDB_LOG_DATAFORMATTERS
Definition: Logging.h:43
A class that represents a running process on the host machine.
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
Definition: ConstString.h:223
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
A TypeSystem implementation based on Clang.
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override
size_t GetIndexOfChildWithName(ConstString name) override
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
#define LLDB_LOG_ERROR(log, error,...)
Definition: Log.h:265
CompilerType GetBasicType(lldb::BasicType type)
#define UINT32_MAX
Definition: lldb-defines.h:31
SyntheticChildrenFrontEnd * BlockPointerSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
virtual lldb::ValueObjectSP GetChildAtIndex(size_t idx)=0
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
bool Success() const
Test for success condition.
Definition: Status.cpp:288
static size_t CalculateNumChildren(CompilerType container_type, CompilerType element_type, lldb_private::ExecutionContextScope *exe_scope=nullptr)
Definition: VectorType.cpp:169
CompilerType GetChildCompilerTypeAtIndex(ExecutionContext *exe_ctx, size_t idx, bool transparent_pointers, bool omit_empty_base_classes, bool ignore_array_bounds, std::string &child_name, uint32_t &child_byte_size, int32_t &child_byte_offset, uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset, bool &child_is_base_class, bool &child_is_deref_of_parent, ValueObject *valobj, uint64_t &language_flags) const
BlockPointerSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
virtual size_t GetIndexOfChildWithName(ConstString name)=0
A uniqued constant string class.
Definition: ConstString.h:40
Log * GetLogIfAnyCategoriesSet(uint32_t mask)
Definition: Logging.cpp:62
Definition: SBAddress.h:15
Represents a generic type in a programming language.
Definition: CompilerType.h:33
lldb::ValueObjectSP GetSP()
Definition: ValueObject.h:539
bool IsBlockPointerType(CompilerType *function_pointer_type_ptr) const
CompilerType CreateStructForIdentifier(ConstString type_name, const std::initializer_list< std::pair< const char *, CompilerType >> &type_fields, bool packed=false)
An error handling class.
Definition: Status.h:44