xref: /freebsd/contrib/llvm-project/lldb/source/DataFormatters/TypeSynthetic.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 
AddExpressionPath(const std::string & path)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(path);
33   else
34     m_expression_paths.push_back(std::string(".") + path);
35 }
36 
SetExpressionPathAtIndex(size_t i,const std::string & path)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>
GetIndexOfChildWithName(ConstString name)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(name_cstr, expr_cstr))
66           return i;
67       }
68     }
69   }
70   return llvm::createStringError("Type has no child named '%s'",
71                                  name.AsCString());
72 }
73 
GetDescription()74 std::string TypeFilterImpl::GetDescription() {
75   StreamString sstr;
76   sstr.Printf("%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("    %s\n", GetExpressionPathAtIndex(i));
82   }
83 
84   sstr.Printf("}");
85   return std::string(sstr.GetString());
86 }
87 
SyntheticChildren(const Flags & flags)88 SyntheticChildren::SyntheticChildren(const Flags &flags) : m_flags(flags) {}
89 
90 SyntheticChildren::~SyntheticChildren() = default;
91 
CXXSyntheticChildren(const SyntheticChildren::Flags & flags,const char * description,CreateFrontEndCallback callback)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 
IsScripted()100 bool SyntheticChildren::IsScripted() { return false; }
101 
GetDescription()102 std::string SyntheticChildren::GetDescription() { return ""; }
103 
104 SyntheticChildrenFrontEnd::AutoPointer
GetFrontEnd(ValueObject & backend)105 SyntheticChildren::GetFrontEnd(ValueObject &backend) {
106   return nullptr;
107 }
108 
GetDescription()109 std::string CXXSyntheticChildren::GetDescription() {
110   StreamString sstr;
111   sstr.Printf("%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
CalculateNumChildrenIgnoringErrors(uint32_t max)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 
CreateValueObjectFromExpression(llvm::StringRef name,llvm::StringRef expression,const ExecutionContext & exe_ctx)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 
CreateValueObjectFromAddress(llvm::StringRef name,uint64_t address,const ExecutionContext & exe_ctx,CompilerType type,bool do_deref)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 
CreateValueObjectFromData(llvm::StringRef name,const DataExtractor & data,const ExecutionContext & exe_ctx,CompilerType type)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 
FrontEnd(std::string pclass,ValueObject & backend)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         m_python_class.c_str(), backend.GetSP());
176 }
177 
178 ScriptedSyntheticChildren::FrontEnd::~FrontEnd() = default;
179 
180 lldb::ValueObjectSP
GetChildAtIndex(uint32_t idx)181 ScriptedSyntheticChildren::FrontEnd::GetChildAtIndex(uint32_t idx) {
182   if (!m_wrapper_sp || !m_interpreter)
183     return lldb::ValueObjectSP();
184 
185   return m_interpreter->GetChildAtIndex(m_wrapper_sp, idx);
186 }
187 
IsValid()188 bool ScriptedSyntheticChildren::FrontEnd::IsValid() {
189   return (m_wrapper_sp && m_wrapper_sp->IsValid() && m_interpreter);
190 }
191 
192 llvm::Expected<uint32_t>
CalculateNumChildren()193 ScriptedSyntheticChildren::FrontEnd::CalculateNumChildren() {
194   if (!m_wrapper_sp || m_interpreter == nullptr)
195     return 0;
196   return m_interpreter->CalculateNumChildren(m_wrapper_sp, UINT32_MAX);
197 }
198 
199 llvm::Expected<uint32_t>
CalculateNumChildren(uint32_t max)200 ScriptedSyntheticChildren::FrontEnd::CalculateNumChildren(uint32_t max) {
201   if (!m_wrapper_sp || m_interpreter == nullptr)
202     return 0;
203   return m_interpreter->CalculateNumChildren(m_wrapper_sp, max);
204 }
205 
Update()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(m_wrapper_sp)
211              ? lldb::ChildCacheState::eReuse
212              : lldb::ChildCacheState::eRefetch;
213 }
214 
MightHaveChildren()215 bool ScriptedSyntheticChildren::FrontEnd::MightHaveChildren() {
216   if (!m_wrapper_sp || m_interpreter == nullptr)
217     return false;
218 
219   return m_interpreter->MightHaveChildrenSynthProviderInstance(m_wrapper_sp);
220 }
221 
222 llvm::Expected<size_t>
GetIndexOfChildWithName(ConstString name)223 ScriptedSyntheticChildren::FrontEnd::GetIndexOfChildWithName(ConstString name) {
224   if (!m_wrapper_sp || m_interpreter == nullptr)
225     return llvm::createStringError("Type has no child named '%s'",
226                                    name.AsCString());
227   return m_interpreter->GetIndexOfChildWithName(m_wrapper_sp,
228                                                 name.GetCString());
229 }
230 
GetSyntheticValue()231 lldb::ValueObjectSP ScriptedSyntheticChildren::FrontEnd::GetSyntheticValue() {
232   if (!m_wrapper_sp || m_interpreter == nullptr)
233     return nullptr;
234 
235   return m_interpreter->GetSyntheticValue(m_wrapper_sp);
236 }
237 
GetSyntheticTypeName()238 ConstString ScriptedSyntheticChildren::FrontEnd::GetSyntheticTypeName() {
239   if (!m_wrapper_sp || m_interpreter == nullptr)
240     return ConstString();
241 
242   return m_interpreter->GetSyntheticTypeName(m_wrapper_sp);
243 }
244 
GetDescription()245 std::string ScriptedSyntheticChildren::GetDescription() {
246   StreamString sstr;
247   sstr.Printf("%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