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 23using namespace lldb; 24using namespace lldb_private; 25 26void 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 37bool 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 52size_t 53TypeFilterImpl::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 UINT32_MAX; 71} 72 73std::string TypeFilterImpl::GetDescription() { 74 StreamString sstr; 75 sstr.Printf("%s%s%s {\n", Cascades() ? "" : " (not cascading)", 76 SkipsPointers() ? " (skip pointers)" : "", 77 SkipsReferences() ? " (skip references)" : ""); 78 79 for (size_t i = 0; i < GetCount(); i++) { 80 sstr.Printf(" %s\n", GetExpressionPathAtIndex(i)); 81 } 82 83 sstr.Printf("}"); 84 return std::string(sstr.GetString()); 85} 86 87SyntheticChildren::SyntheticChildren(const Flags &flags) : m_flags(flags) {} 88 89SyntheticChildren::~SyntheticChildren() = default; 90 91CXXSyntheticChildren::CXXSyntheticChildren( 92 const SyntheticChildren::Flags &flags, const char *description, 93 CreateFrontEndCallback callback) 94 : SyntheticChildren(flags), m_create_callback(std::move(callback)), 95 m_description(description ? description : "") {} 96 97CXXSyntheticChildren::~CXXSyntheticChildren() = default; 98 99bool SyntheticChildren::IsScripted() { return false; } 100 101std::string SyntheticChildren::GetDescription() { return ""; } 102 103SyntheticChildrenFrontEnd::AutoPointer 104SyntheticChildren::GetFrontEnd(ValueObject &backend) { 105 return nullptr; 106} 107 108std::string CXXSyntheticChildren::GetDescription() { 109 StreamString sstr; 110 sstr.Printf("%s%s%s %s", Cascades() ? "" : " (not cascading)", 111 SkipsPointers() ? " (skip pointers)" : "", 112 SkipsReferences() ? " (skip references)" : "", 113 m_description.c_str()); 114 115 return std::string(sstr.GetString()); 116} 117 118lldb::ValueObjectSP SyntheticChildrenFrontEnd::CreateValueObjectFromExpression( 119 llvm::StringRef name, llvm::StringRef expression, 120 const ExecutionContext &exe_ctx) { 121 ValueObjectSP valobj_sp( 122 ValueObject::CreateValueObjectFromExpression(name, expression, exe_ctx)); 123 if (valobj_sp) 124 valobj_sp->SetSyntheticChildrenGenerated(true); 125 return valobj_sp; 126} 127 128lldb::ValueObjectSP SyntheticChildrenFrontEnd::CreateValueObjectFromAddress( 129 llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx, 130 CompilerType type) { 131 ValueObjectSP valobj_sp( 132 ValueObject::CreateValueObjectFromAddress(name, address, exe_ctx, type)); 133 if (valobj_sp) 134 valobj_sp->SetSyntheticChildrenGenerated(true); 135 return valobj_sp; 136} 137 138lldb::ValueObjectSP SyntheticChildrenFrontEnd::CreateValueObjectFromData( 139 llvm::StringRef name, const DataExtractor &data, 140 const ExecutionContext &exe_ctx, CompilerType type) { 141 ValueObjectSP valobj_sp( 142 ValueObject::CreateValueObjectFromData(name, data, exe_ctx, type)); 143 if (valobj_sp) 144 valobj_sp->SetSyntheticChildrenGenerated(true); 145 return valobj_sp; 146} 147 148ScriptedSyntheticChildren::FrontEnd::FrontEnd(std::string pclass, 149 ValueObject &backend) 150 : SyntheticChildrenFrontEnd(backend), m_python_class(pclass), 151 m_wrapper_sp(), m_interpreter(nullptr) { 152 if (backend.GetID() == LLDB_INVALID_UID) 153 return; 154 155 TargetSP target_sp = backend.GetTargetSP(); 156 157 if (!target_sp) 158 return; 159 160 m_interpreter = target_sp->GetDebugger().GetScriptInterpreter(); 161 162 if (m_interpreter != nullptr) 163 m_wrapper_sp = m_interpreter->CreateSyntheticScriptedProvider( 164 m_python_class.c_str(), backend.GetSP()); 165} 166 167ScriptedSyntheticChildren::FrontEnd::~FrontEnd() = default; 168 169lldb::ValueObjectSP 170ScriptedSyntheticChildren::FrontEnd::GetChildAtIndex(size_t idx) { 171 if (!m_wrapper_sp || !m_interpreter) 172 return lldb::ValueObjectSP(); 173 174 return m_interpreter->GetChildAtIndex(m_wrapper_sp, idx); 175} 176 177bool ScriptedSyntheticChildren::FrontEnd::IsValid() { 178 return (m_wrapper_sp && m_wrapper_sp->IsValid() && m_interpreter); 179} 180 181size_t ScriptedSyntheticChildren::FrontEnd::CalculateNumChildren() { 182 if (!m_wrapper_sp || m_interpreter == nullptr) 183 return 0; 184 return m_interpreter->CalculateNumChildren(m_wrapper_sp, UINT32_MAX); 185} 186 187size_t ScriptedSyntheticChildren::FrontEnd::CalculateNumChildren(uint32_t max) { 188 if (!m_wrapper_sp || m_interpreter == nullptr) 189 return 0; 190 return m_interpreter->CalculateNumChildren(m_wrapper_sp, max); 191} 192 193bool ScriptedSyntheticChildren::FrontEnd::Update() { 194 if (!m_wrapper_sp || m_interpreter == nullptr) 195 return false; 196 197 return m_interpreter->UpdateSynthProviderInstance(m_wrapper_sp); 198} 199 200bool ScriptedSyntheticChildren::FrontEnd::MightHaveChildren() { 201 if (!m_wrapper_sp || m_interpreter == nullptr) 202 return false; 203 204 return m_interpreter->MightHaveChildrenSynthProviderInstance(m_wrapper_sp); 205} 206 207size_t ScriptedSyntheticChildren::FrontEnd::GetIndexOfChildWithName( 208 ConstString name) { 209 if (!m_wrapper_sp || m_interpreter == nullptr) 210 return UINT32_MAX; 211 return m_interpreter->GetIndexOfChildWithName(m_wrapper_sp, 212 name.GetCString()); 213} 214 215lldb::ValueObjectSP ScriptedSyntheticChildren::FrontEnd::GetSyntheticValue() { 216 if (!m_wrapper_sp || m_interpreter == nullptr) 217 return nullptr; 218 219 return m_interpreter->GetSyntheticValue(m_wrapper_sp); 220} 221 222ConstString ScriptedSyntheticChildren::FrontEnd::GetSyntheticTypeName() { 223 if (!m_wrapper_sp || m_interpreter == nullptr) 224 return ConstString(); 225 226 return m_interpreter->GetSyntheticTypeName(m_wrapper_sp); 227} 228 229std::string ScriptedSyntheticChildren::GetDescription() { 230 StreamString sstr; 231 sstr.Printf("%s%s%s Python class %s", Cascades() ? "" : " (not cascading)", 232 SkipsPointers() ? " (skip pointers)" : "", 233 SkipsReferences() ? " (skip references)" : "", 234 m_python_class.c_str()); 235 236 return std::string(sstr.GetString()); 237} 238