Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
39642 views
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
11
#include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"
12
#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
13
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
14
#include "lldb/Core/ValueObject.h"
15
#include "lldb/Core/ValueObjectConstResult.h"
16
#include "lldb/DataFormatters/FormattersHelpers.h"
17
#include "lldb/Symbol/CompilerType.h"
18
#include "lldb/Symbol/TypeSystem.h"
19
#include "lldb/Target/Target.h"
20
#include "lldb/Utility/LLDBAssert.h"
21
#include "lldb/Utility/LLDBLog.h"
22
#include "lldb/Utility/Log.h"
23
24
using namespace lldb;
25
using namespace lldb_private;
26
using namespace lldb_private::formatters;
27
28
namespace lldb_private {
29
namespace formatters {
30
31
class BlockPointerSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
32
public:
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 ts = block_pointer_type.GetTypeSystem();
54
auto clang_ast_context = ts.dyn_cast_or_null<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(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 ever
142
// updating again; the typical (and tested) answer here is 'false'
143
lldb::ChildCacheState Update() override {
144
return lldb::ChildCacheState::eRefetch;
145
}
146
147
// maybe return false if the block pointer is, say, null
148
bool MightHaveChildren() override { return true; }
149
150
size_t GetIndexOfChildWithName(ConstString name) override {
151
if (!m_block_struct_type.IsValid())
152
return UINT32_MAX;
153
154
const bool omit_empty_base_classes = false;
155
return m_block_struct_type.GetIndexOfChildWithName(name.AsCString(),
156
omit_empty_base_classes);
157
}
158
159
private:
160
CompilerType m_block_struct_type;
161
};
162
163
} // namespace formatters
164
} // namespace lldb_private
165
166
bool lldb_private::formatters::BlockPointerSummaryProvider(
167
ValueObject &valobj, Stream &s, const TypeSummaryOptions &) {
168
lldb_private::SyntheticChildrenFrontEnd *synthetic_children =
169
BlockPointerSyntheticFrontEndCreator(nullptr, valobj.GetSP());
170
if (!synthetic_children) {
171
return false;
172
}
173
174
synthetic_children->Update();
175
176
static const ConstString s_FuncPtr_name("__FuncPtr");
177
178
lldb::ValueObjectSP child_sp = synthetic_children->GetChildAtIndex(
179
synthetic_children->GetIndexOfChildWithName(s_FuncPtr_name));
180
181
if (!child_sp) {
182
return false;
183
}
184
185
lldb::ValueObjectSP qualified_child_representation_sp =
186
child_sp->GetQualifiedRepresentationIfAvailable(
187
lldb::eDynamicDontRunTarget, true);
188
189
const char *child_value =
190
qualified_child_representation_sp->GetValueAsCString();
191
192
s.Printf("%s", child_value);
193
194
return true;
195
}
196
197
lldb_private::SyntheticChildrenFrontEnd *
198
lldb_private::formatters::BlockPointerSyntheticFrontEndCreator(
199
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
200
if (!valobj_sp)
201
return nullptr;
202
return new BlockPointerSyntheticFrontEnd(valobj_sp);
203
}
204
205