1 | //===-- TypeSynthetic.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 | |
10 | |
11 | |
12 | #include "lldb/lldb-enumerations.h" |
13 | #include "lldb/lldb-public.h" |
14 | |
15 | #include "lldb/Core/Debugger.h" |
16 | #include "lldb/DataFormatters/TypeSynthetic.h" |
17 | #include "lldb/Interpreter/CommandInterpreter.h" |
18 | #include "lldb/Interpreter/ScriptInterpreter.h" |
19 | #include "lldb/Symbol/CompilerType.h" |
20 | #include "lldb/Target/Target.h" |
21 | #include "lldb/Utility/StreamString.h" |
22 | |
23 | using namespace lldb; |
24 | using namespace lldb_private; |
25 | |
26 | void TypeFilterImpl::AddExpressionPath(const std::string &path) { |
27 | bool need_add_dot = true; |
28 | if (path[0] == '.' || (path[0] == '-' && path[1] == '>') || path[0] == '[') |
29 | need_add_dot = false; |
30 | // add a '.' symbol to help forgetful users |
31 | if (!need_add_dot) |
32 | m_expression_paths.push_back(x: path); |
33 | else |
34 | m_expression_paths.push_back(x: std::string(".") + path); |
35 | } |
36 | |
37 | bool TypeFilterImpl::SetExpressionPathAtIndex(size_t i, |
38 | const std::string &path) { |
39 | if (i >= GetCount()) |
40 | return false; |
41 | bool need_add_dot = true; |
42 | if (path[0] == '.' || (path[0] == '-' && path[1] == '>') || path[0] == '[') |
43 | need_add_dot = false; |
44 | // add a '.' symbol to help forgetful users |
45 | if (!need_add_dot) |
46 | m_expression_paths[i] = path; |
47 | else |
48 | m_expression_paths[i] = std::string(".") + path; |
49 | return true; |
50 | } |
51 | |
52 | llvm::Expected<size_t> |
53 | TypeFilterImpl::FrontEnd::GetIndexOfChildWithName(ConstString name) { |
54 | const char *name_cstr = name.GetCString(); |
55 | if (name_cstr) { |
56 | for (size_t i = 0; i < filter->GetCount(); i++) { |
57 | const char *expr_cstr = filter->GetExpressionPathAtIndex(i); |
58 | if (expr_cstr) { |
59 | if (*expr_cstr == '.') |
60 | expr_cstr++; |
61 | else if (*expr_cstr == '-' && *(expr_cstr + 1) == '>') |
62 | expr_cstr += 2; |
63 | } |
64 | if (expr_cstr) { |
65 | if (!::strcmp(s1: name_cstr, s2: expr_cstr)) |
66 | return i; |
67 | } |
68 | } |
69 | } |
70 | return llvm::createStringError(Fmt: "Type has no child named '%s'", |
71 | Vals: name.AsCString()); |
72 | } |
73 | |
74 | std::string TypeFilterImpl::GetDescription() { |
75 | StreamString sstr; |
76 | sstr.Printf(format: "%s%s%s {\n", Cascades() ? "": " (not cascading)", |
77 | SkipsPointers() ? " (skip pointers)": "", |
78 | SkipsReferences() ? " (skip references)": ""); |
79 | |
80 | for (size_t i = 0; i < GetCount(); i++) { |
81 | sstr.Printf(format: " %s\n", GetExpressionPathAtIndex(i)); |
82 | } |
83 | |
84 | sstr.Printf(format: "}"); |
85 | return std::string(sstr.GetString()); |
86 | } |
87 | |
88 | SyntheticChildren::SyntheticChildren(const Flags &flags) : m_flags(flags) {} |
89 | |
90 | SyntheticChildren::~SyntheticChildren() = default; |
91 | |
92 | CXXSyntheticChildren::CXXSyntheticChildren( |
93 | const SyntheticChildren::Flags &flags, const char *description, |
94 | CreateFrontEndCallback callback) |
95 | : SyntheticChildren(flags), m_create_callback(std::move(callback)), |
96 | m_description(description ? description : "") {} |
97 | |
98 | CXXSyntheticChildren::~CXXSyntheticChildren() = default; |
99 | |
100 | bool SyntheticChildren::IsScripted() { return false; } |
101 | |
102 | std::string SyntheticChildren::GetDescription() { return ""; } |
103 | |
104 | SyntheticChildrenFrontEnd::AutoPointer |
105 | SyntheticChildren::GetFrontEnd(ValueObject &backend) { |
106 | return nullptr; |
107 | } |
108 | |
109 | std::string CXXSyntheticChildren::GetDescription() { |
110 | StreamString sstr; |
111 | sstr.Printf(format: "%s%s%s %s", Cascades() ? "": " (not cascading)", |
112 | SkipsPointers() ? " (skip pointers)": "", |
113 | SkipsReferences() ? " (skip references)": "", |
114 | m_description.c_str()); |
115 | |
116 | return std::string(sstr.GetString()); |
117 | } |
118 | |
119 | uint32_t |
120 | SyntheticChildrenFrontEnd::CalculateNumChildrenIgnoringErrors(uint32_t max) { |
121 | auto value_or_err = CalculateNumChildren(max); |
122 | if (value_or_err) |
123 | return *value_or_err; |
124 | LLDB_LOG_ERRORV(GetLog(LLDBLog::DataFormatters), value_or_err.takeError(), |
125 | "{0}"); |
126 | return 0; |
127 | } |
128 | |
129 | lldb::ValueObjectSP SyntheticChildrenFrontEnd::CreateValueObjectFromExpression( |
130 | llvm::StringRef name, llvm::StringRef expression, |
131 | const ExecutionContext &exe_ctx) { |
132 | ValueObjectSP valobj_sp( |
133 | ValueObject::CreateValueObjectFromExpression(name, expression, exe_ctx)); |
134 | if (valobj_sp) |
135 | valobj_sp->SetSyntheticChildrenGenerated(true); |
136 | return valobj_sp; |
137 | } |
138 | |
139 | lldb::ValueObjectSP SyntheticChildrenFrontEnd::CreateValueObjectFromAddress( |
140 | llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx, |
141 | CompilerType type, bool do_deref) { |
142 | ValueObjectSP valobj_sp(ValueObject::CreateValueObjectFromAddress( |
143 | name, address, exe_ctx, type, do_deref)); |
144 | if (valobj_sp) |
145 | valobj_sp->SetSyntheticChildrenGenerated(true); |
146 | return valobj_sp; |
147 | } |
148 | |
149 | lldb::ValueObjectSP SyntheticChildrenFrontEnd::CreateValueObjectFromData( |
150 | llvm::StringRef name, const DataExtractor &data, |
151 | const ExecutionContext &exe_ctx, CompilerType type) { |
152 | ValueObjectSP valobj_sp( |
153 | ValueObject::CreateValueObjectFromData(name, data, exe_ctx, type)); |
154 | if (valobj_sp) |
155 | valobj_sp->SetSyntheticChildrenGenerated(true); |
156 | return valobj_sp; |
157 | } |
158 | |
159 | ScriptedSyntheticChildren::FrontEnd::FrontEnd(std::string pclass, |
160 | ValueObject &backend) |
161 | : SyntheticChildrenFrontEnd(backend), m_python_class(pclass), |
162 | m_wrapper_sp(), m_interpreter(nullptr) { |
163 | if (backend.GetID() == LLDB_INVALID_UID) |
164 | return; |
165 | |
166 | TargetSP target_sp = backend.GetTargetSP(); |
167 | |
168 | if (!target_sp) |
169 | return; |
170 | |
171 | m_interpreter = target_sp->GetDebugger().GetScriptInterpreter(); |
172 | |
173 | if (m_interpreter != nullptr) |
174 | m_wrapper_sp = m_interpreter->CreateSyntheticScriptedProvider( |
175 | class_name: m_python_class.c_str(), valobj: backend.GetSP()); |
176 | } |
177 | |
178 | ScriptedSyntheticChildren::FrontEnd::~FrontEnd() = default; |
179 | |
180 | lldb::ValueObjectSP |
181 | ScriptedSyntheticChildren::FrontEnd::GetChildAtIndex(uint32_t idx) { |
182 | if (!m_wrapper_sp || !m_interpreter) |
183 | return lldb::ValueObjectSP(); |
184 | |
185 | return m_interpreter->GetChildAtIndex(implementor: m_wrapper_sp, idx); |
186 | } |
187 | |
188 | bool ScriptedSyntheticChildren::FrontEnd::IsValid() { |
189 | return (m_wrapper_sp && m_wrapper_sp->IsValid() && m_interpreter); |
190 | } |
191 | |
192 | llvm::Expected<uint32_t> |
193 | ScriptedSyntheticChildren::FrontEnd::CalculateNumChildren() { |
194 | if (!m_wrapper_sp || m_interpreter == nullptr) |
195 | return 0; |
196 | return m_interpreter->CalculateNumChildren(implementor: m_wrapper_sp, UINT32_MAX); |
197 | } |
198 | |
199 | llvm::Expected<uint32_t> |
200 | ScriptedSyntheticChildren::FrontEnd::CalculateNumChildren(uint32_t max) { |
201 | if (!m_wrapper_sp || m_interpreter == nullptr) |
202 | return 0; |
203 | return m_interpreter->CalculateNumChildren(implementor: m_wrapper_sp, max); |
204 | } |
205 | |
206 | lldb::ChildCacheState ScriptedSyntheticChildren::FrontEnd::Update() { |
207 | if (!m_wrapper_sp || m_interpreter == nullptr) |
208 | return lldb::ChildCacheState::eRefetch; |
209 | |
210 | return m_interpreter->UpdateSynthProviderInstance(implementor: m_wrapper_sp) |
211 | ? lldb::ChildCacheState::eReuse |
212 | : lldb::ChildCacheState::eRefetch; |
213 | } |
214 | |
215 | bool ScriptedSyntheticChildren::FrontEnd::MightHaveChildren() { |
216 | if (!m_wrapper_sp || m_interpreter == nullptr) |
217 | return false; |
218 | |
219 | return m_interpreter->MightHaveChildrenSynthProviderInstance(implementor: m_wrapper_sp); |
220 | } |
221 | |
222 | llvm::Expected<size_t> |
223 | ScriptedSyntheticChildren::FrontEnd::GetIndexOfChildWithName(ConstString name) { |
224 | if (!m_wrapper_sp || m_interpreter == nullptr) |
225 | return llvm::createStringError(Fmt: "Type has no child named '%s'", |
226 | Vals: name.AsCString()); |
227 | return m_interpreter->GetIndexOfChildWithName(implementor: m_wrapper_sp, |
228 | child_name: name.GetCString()); |
229 | } |
230 | |
231 | lldb::ValueObjectSP ScriptedSyntheticChildren::FrontEnd::GetSyntheticValue() { |
232 | if (!m_wrapper_sp || m_interpreter == nullptr) |
233 | return nullptr; |
234 | |
235 | return m_interpreter->GetSyntheticValue(implementor: m_wrapper_sp); |
236 | } |
237 | |
238 | ConstString ScriptedSyntheticChildren::FrontEnd::GetSyntheticTypeName() { |
239 | if (!m_wrapper_sp || m_interpreter == nullptr) |
240 | return ConstString(); |
241 | |
242 | return m_interpreter->GetSyntheticTypeName(implementor: m_wrapper_sp); |
243 | } |
244 | |
245 | std::string ScriptedSyntheticChildren::GetDescription() { |
246 | StreamString sstr; |
247 | sstr.Printf(format: "%s%s%s Python class %s", Cascades() ? "": " (not cascading)", |
248 | SkipsPointers() ? " (skip pointers)": "", |
249 | SkipsReferences() ? " (skip references)": "", |
250 | m_python_class.c_str()); |
251 | |
252 | return std::string(sstr.GetString()); |
253 | } |
254 |
Definitions
- AddExpressionPath
- SetExpressionPathAtIndex
- GetIndexOfChildWithName
- GetDescription
- SyntheticChildren
- ~SyntheticChildren
- CXXSyntheticChildren
- ~CXXSyntheticChildren
- IsScripted
- GetDescription
- GetFrontEnd
- GetDescription
- CalculateNumChildrenIgnoringErrors
- CreateValueObjectFromExpression
- CreateValueObjectFromAddress
- CreateValueObjectFromData
- FrontEnd
- ~FrontEnd
- GetChildAtIndex
- IsValid
- CalculateNumChildren
- CalculateNumChildren
- Update
- MightHaveChildren
- GetIndexOfChildWithName
- GetSyntheticValue
- GetSyntheticTypeName
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more