1 //===-- TypeSynthetic.cpp ----------------------------------------*- C++ 2 //-*-===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 11 12 13 #include "lldb/lldb-enumerations.h" 14 #include "lldb/lldb-public.h" 15 16 #include "lldb/Core/Debugger.h" 17 #include "lldb/DataFormatters/TypeSynthetic.h" 18 #include "lldb/Interpreter/CommandInterpreter.h" 19 #include "lldb/Interpreter/ScriptInterpreter.h" 20 #include "lldb/Symbol/CompilerType.h" 21 #include "lldb/Target/Target.h" 22 #include "lldb/Utility/StreamString.h" 23 24 using namespace lldb; 25 using namespace lldb_private; 26 27 void TypeFilterImpl::AddExpressionPath(const std::string &path) { 28 bool need_add_dot = true; 29 if (path[0] == '.' || (path[0] == '-' && path[1] == '>') || path[0] == '[') 30 need_add_dot = false; 31 // add a '.' symbol to help forgetful users 32 if (!need_add_dot) 33 m_expression_paths.push_back(path); 34 else 35 m_expression_paths.push_back(std::string(".") + path); 36 } 37 38 bool TypeFilterImpl::SetExpressionPathAtIndex(size_t i, 39 const std::string &path) { 40 if (i >= GetCount()) 41 return false; 42 bool need_add_dot = true; 43 if (path[0] == '.' || (path[0] == '-' && path[1] == '>') || path[0] == '[') 44 need_add_dot = false; 45 // add a '.' symbol to help forgetful users 46 if (!need_add_dot) 47 m_expression_paths[i] = path; 48 else 49 m_expression_paths[i] = std::string(".") + path; 50 return true; 51 } 52 53 size_t 54 TypeFilterImpl::FrontEnd::GetIndexOfChildWithName(ConstString name) { 55 const char *name_cstr = name.GetCString(); 56 if (name_cstr) { 57 for (size_t i = 0; i < filter->GetCount(); i++) { 58 const char *expr_cstr = filter->GetExpressionPathAtIndex(i); 59 if (expr_cstr) { 60 if (*expr_cstr == '.') 61 expr_cstr++; 62 else if (*expr_cstr == '-' && *(expr_cstr + 1) == '>') 63 expr_cstr += 2; 64 } 65 if (expr_cstr) { 66 if (!::strcmp(name_cstr, expr_cstr)) 67 return i; 68 } 69 } 70 } 71 return UINT32_MAX; 72 } 73 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 sstr.GetString(); 86 } 87 88 std::string CXXSyntheticChildren::GetDescription() { 89 StreamString sstr; 90 sstr.Printf("%s%s%s %s", Cascades() ? "" : " (not cascading)", 91 SkipsPointers() ? " (skip pointers)" : "", 92 SkipsReferences() ? " (skip references)" : "", 93 m_description.c_str()); 94 95 return sstr.GetString(); 96 } 97 98 lldb::ValueObjectSP SyntheticChildrenFrontEnd::CreateValueObjectFromExpression( 99 llvm::StringRef name, llvm::StringRef expression, 100 const ExecutionContext &exe_ctx) { 101 ValueObjectSP valobj_sp( 102 ValueObject::CreateValueObjectFromExpression(name, expression, exe_ctx)); 103 if (valobj_sp) 104 valobj_sp->SetSyntheticChildrenGenerated(true); 105 return valobj_sp; 106 } 107 108 lldb::ValueObjectSP SyntheticChildrenFrontEnd::CreateValueObjectFromAddress( 109 llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx, 110 CompilerType type) { 111 ValueObjectSP valobj_sp( 112 ValueObject::CreateValueObjectFromAddress(name, address, exe_ctx, type)); 113 if (valobj_sp) 114 valobj_sp->SetSyntheticChildrenGenerated(true); 115 return valobj_sp; 116 } 117 118 lldb::ValueObjectSP SyntheticChildrenFrontEnd::CreateValueObjectFromData( 119 llvm::StringRef name, const DataExtractor &data, 120 const ExecutionContext &exe_ctx, CompilerType type) { 121 ValueObjectSP valobj_sp( 122 ValueObject::CreateValueObjectFromData(name, data, exe_ctx, type)); 123 if (valobj_sp) 124 valobj_sp->SetSyntheticChildrenGenerated(true); 125 return valobj_sp; 126 } 127 128 ScriptedSyntheticChildren::FrontEnd::FrontEnd(std::string pclass, 129 ValueObject &backend) 130 : SyntheticChildrenFrontEnd(backend), m_python_class(pclass), 131 m_wrapper_sp(), m_interpreter(nullptr) { 132 if (backend == LLDB_INVALID_UID) 133 return; 134 135 TargetSP target_sp = backend.GetTargetSP(); 136 137 if (!target_sp) 138 return; 139 140 m_interpreter = target_sp->GetDebugger().GetScriptInterpreter(); 141 142 if (m_interpreter != nullptr) 143 m_wrapper_sp = m_interpreter->CreateSyntheticScriptedProvider( 144 m_python_class.c_str(), backend.GetSP()); 145 } 146 147 ScriptedSyntheticChildren::FrontEnd::~FrontEnd() {} 148 149 lldb::ValueObjectSP 150 ScriptedSyntheticChildren::FrontEnd::GetChildAtIndex(size_t idx) { 151 if (!m_wrapper_sp || !m_interpreter) 152 return lldb::ValueObjectSP(); 153 154 return m_interpreter->GetChildAtIndex(m_wrapper_sp, idx); 155 } 156 157 bool ScriptedSyntheticChildren::FrontEnd::IsValid() { 158 return (m_wrapper_sp && m_wrapper_sp->IsValid() && m_interpreter); 159 } 160 161 size_t ScriptedSyntheticChildren::FrontEnd::CalculateNumChildren() { 162 if (!m_wrapper_sp || m_interpreter == nullptr) 163 return 0; 164 return m_interpreter->CalculateNumChildren(m_wrapper_sp, UINT32_MAX); 165 } 166 167 size_t ScriptedSyntheticChildren::FrontEnd::CalculateNumChildren(uint32_t max) { 168 if (!m_wrapper_sp || m_interpreter == nullptr) 169 return 0; 170 return m_interpreter->CalculateNumChildren(m_wrapper_sp, max); 171 } 172 173 bool ScriptedSyntheticChildren::FrontEnd::Update() { 174 if (!m_wrapper_sp || m_interpreter == nullptr) 175 return false; 176 177 return m_interpreter->UpdateSynthProviderInstance(m_wrapper_sp); 178 } 179 180 bool ScriptedSyntheticChildren::FrontEnd::MightHaveChildren() { 181 if (!m_wrapper_sp || m_interpreter == nullptr) 182 return false; 183 184 return m_interpreter->MightHaveChildrenSynthProviderInstance(m_wrapper_sp); 185 } 186 187 size_t ScriptedSyntheticChildren::FrontEnd::GetIndexOfChildWithName( 188 ConstString name) { 189 if (!m_wrapper_sp || m_interpreter == nullptr) 190 return UINT32_MAX; 191 return m_interpreter->GetIndexOfChildWithName(m_wrapper_sp, 192 name.GetCString()); 193 } 194 195 lldb::ValueObjectSP ScriptedSyntheticChildren::FrontEnd::GetSyntheticValue() { 196 if (!m_wrapper_sp || m_interpreter == nullptr) 197 return nullptr; 198 199 return m_interpreter->GetSyntheticValue(m_wrapper_sp); 200 } 201 202 ConstString ScriptedSyntheticChildren::FrontEnd::GetSyntheticTypeName() { 203 if (!m_wrapper_sp || m_interpreter == nullptr) 204 return ConstString(); 205 206 return m_interpreter->GetSyntheticTypeName(m_wrapper_sp); 207 } 208 209 std::string ScriptedSyntheticChildren::GetDescription() { 210 StreamString sstr; 211 sstr.Printf("%s%s%s Python class %s", Cascades() ? "" : " (not cascading)", 212 SkipsPointers() ? " (skip pointers)" : "", 213 SkipsReferences() ? " (skip references)" : "", 214 m_python_class.c_str()); 215 216 return sstr.GetString(); 217 } 218