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(path); 33 else 34 m_expression_paths.push_back(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 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(name_cstr, expr_cstr)) 66 return i; 67 } 68 } 69 } 70 return UINT32_MAX; 71 } 72 73 std::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 87 std::string CXXSyntheticChildren::GetDescription() { 88 StreamString sstr; 89 sstr.Printf("%s%s%s %s", Cascades() ? "" : " (not cascading)", 90 SkipsPointers() ? " (skip pointers)" : "", 91 SkipsReferences() ? " (skip references)" : "", 92 m_description.c_str()); 93 94 return std::string(sstr.GetString()); 95 } 96 97 lldb::ValueObjectSP SyntheticChildrenFrontEnd::CreateValueObjectFromExpression( 98 llvm::StringRef name, llvm::StringRef expression, 99 const ExecutionContext &exe_ctx) { 100 ValueObjectSP valobj_sp( 101 ValueObject::CreateValueObjectFromExpression(name, expression, exe_ctx)); 102 if (valobj_sp) 103 valobj_sp->SetSyntheticChildrenGenerated(true); 104 return valobj_sp; 105 } 106 107 lldb::ValueObjectSP SyntheticChildrenFrontEnd::CreateValueObjectFromAddress( 108 llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx, 109 CompilerType type) { 110 ValueObjectSP valobj_sp( 111 ValueObject::CreateValueObjectFromAddress(name, address, exe_ctx, type)); 112 if (valobj_sp) 113 valobj_sp->SetSyntheticChildrenGenerated(true); 114 return valobj_sp; 115 } 116 117 lldb::ValueObjectSP SyntheticChildrenFrontEnd::CreateValueObjectFromData( 118 llvm::StringRef name, const DataExtractor &data, 119 const ExecutionContext &exe_ctx, CompilerType type) { 120 ValueObjectSP valobj_sp( 121 ValueObject::CreateValueObjectFromData(name, data, exe_ctx, type)); 122 if (valobj_sp) 123 valobj_sp->SetSyntheticChildrenGenerated(true); 124 return valobj_sp; 125 } 126 127 ScriptedSyntheticChildren::FrontEnd::FrontEnd(std::string pclass, 128 ValueObject &backend) 129 : SyntheticChildrenFrontEnd(backend), m_python_class(pclass), 130 m_wrapper_sp(), m_interpreter(nullptr) { 131 if (backend.GetID() == LLDB_INVALID_UID) 132 return; 133 134 TargetSP target_sp = backend.GetTargetSP(); 135 136 if (!target_sp) 137 return; 138 139 m_interpreter = target_sp->GetDebugger().GetScriptInterpreter(); 140 141 if (m_interpreter != nullptr) 142 m_wrapper_sp = m_interpreter->CreateSyntheticScriptedProvider( 143 m_python_class.c_str(), backend.GetSP()); 144 } 145 146 ScriptedSyntheticChildren::FrontEnd::~FrontEnd() = default; 147 148 lldb::ValueObjectSP 149 ScriptedSyntheticChildren::FrontEnd::GetChildAtIndex(size_t idx) { 150 if (!m_wrapper_sp || !m_interpreter) 151 return lldb::ValueObjectSP(); 152 153 return m_interpreter->GetChildAtIndex(m_wrapper_sp, idx); 154 } 155 156 bool ScriptedSyntheticChildren::FrontEnd::IsValid() { 157 return (m_wrapper_sp && m_wrapper_sp->IsValid() && m_interpreter); 158 } 159 160 size_t ScriptedSyntheticChildren::FrontEnd::CalculateNumChildren() { 161 if (!m_wrapper_sp || m_interpreter == nullptr) 162 return 0; 163 return m_interpreter->CalculateNumChildren(m_wrapper_sp, UINT32_MAX); 164 } 165 166 size_t ScriptedSyntheticChildren::FrontEnd::CalculateNumChildren(uint32_t max) { 167 if (!m_wrapper_sp || m_interpreter == nullptr) 168 return 0; 169 return m_interpreter->CalculateNumChildren(m_wrapper_sp, max); 170 } 171 172 bool ScriptedSyntheticChildren::FrontEnd::Update() { 173 if (!m_wrapper_sp || m_interpreter == nullptr) 174 return false; 175 176 return m_interpreter->UpdateSynthProviderInstance(m_wrapper_sp); 177 } 178 179 bool ScriptedSyntheticChildren::FrontEnd::MightHaveChildren() { 180 if (!m_wrapper_sp || m_interpreter == nullptr) 181 return false; 182 183 return m_interpreter->MightHaveChildrenSynthProviderInstance(m_wrapper_sp); 184 } 185 186 size_t ScriptedSyntheticChildren::FrontEnd::GetIndexOfChildWithName( 187 ConstString name) { 188 if (!m_wrapper_sp || m_interpreter == nullptr) 189 return UINT32_MAX; 190 return m_interpreter->GetIndexOfChildWithName(m_wrapper_sp, 191 name.GetCString()); 192 } 193 194 lldb::ValueObjectSP ScriptedSyntheticChildren::FrontEnd::GetSyntheticValue() { 195 if (!m_wrapper_sp || m_interpreter == nullptr) 196 return nullptr; 197 198 return m_interpreter->GetSyntheticValue(m_wrapper_sp); 199 } 200 201 ConstString ScriptedSyntheticChildren::FrontEnd::GetSyntheticTypeName() { 202 if (!m_wrapper_sp || m_interpreter == nullptr) 203 return ConstString(); 204 205 return m_interpreter->GetSyntheticTypeName(m_wrapper_sp); 206 } 207 208 std::string ScriptedSyntheticChildren::GetDescription() { 209 StreamString sstr; 210 sstr.Printf("%s%s%s Python class %s", Cascades() ? "" : " (not cascading)", 211 SkipsPointers() ? " (skip pointers)" : "", 212 SkipsReferences() ? " (skip references)" : "", 213 m_python_class.c_str()); 214 215 return std::string(sstr.GetString()); 216 } 217