1 //===-- LanguageRuntime.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 #include "lldb/Target/LanguageRuntime.h" 10 #include "lldb/Core/PluginManager.h" 11 #include "lldb/Core/SearchFilter.h" 12 #include "lldb/Interpreter/CommandInterpreter.h" 13 #include "lldb/Target/Language.h" 14 #include "lldb/Target/Target.h" 15 16 using namespace lldb; 17 using namespace lldb_private; 18 19 char LanguageRuntime::ID = 0; 20 21 ExceptionSearchFilter::ExceptionSearchFilter(const lldb::TargetSP &target_sp, 22 lldb::LanguageType language, 23 bool update_module_list) 24 : SearchFilter(target_sp, FilterTy::Exception), m_language(language), 25 m_language_runtime(nullptr), m_filter_sp() { 26 if (update_module_list) 27 UpdateModuleListIfNeeded(); 28 } 29 30 bool ExceptionSearchFilter::ModulePasses(const lldb::ModuleSP &module_sp) { 31 UpdateModuleListIfNeeded(); 32 if (m_filter_sp) 33 return m_filter_sp->ModulePasses(module_sp); 34 return false; 35 } 36 37 bool ExceptionSearchFilter::ModulePasses(const FileSpec &spec) { 38 UpdateModuleListIfNeeded(); 39 if (m_filter_sp) 40 return m_filter_sp->ModulePasses(spec); 41 return false; 42 } 43 44 void ExceptionSearchFilter::Search(Searcher &searcher) { 45 UpdateModuleListIfNeeded(); 46 if (m_filter_sp) 47 m_filter_sp->Search(searcher); 48 } 49 50 void ExceptionSearchFilter::GetDescription(Stream *s) { 51 UpdateModuleListIfNeeded(); 52 if (m_filter_sp) 53 m_filter_sp->GetDescription(s); 54 } 55 56 void ExceptionSearchFilter::UpdateModuleListIfNeeded() { 57 ProcessSP process_sp(m_target_sp->GetProcessSP()); 58 if (process_sp) { 59 bool refreash_filter = !m_filter_sp; 60 if (m_language_runtime == nullptr) { 61 m_language_runtime = process_sp->GetLanguageRuntime(m_language); 62 refreash_filter = true; 63 } else { 64 LanguageRuntime *language_runtime = 65 process_sp->GetLanguageRuntime(m_language); 66 if (m_language_runtime != language_runtime) { 67 m_language_runtime = language_runtime; 68 refreash_filter = true; 69 } 70 } 71 72 if (refreash_filter && m_language_runtime) { 73 m_filter_sp = m_language_runtime->CreateExceptionSearchFilter(); 74 } 75 } else { 76 m_filter_sp.reset(); 77 m_language_runtime = nullptr; 78 } 79 } 80 81 SearchFilterSP ExceptionSearchFilter::DoCreateCopy() { 82 return SearchFilterSP( 83 new ExceptionSearchFilter(TargetSP(), m_language, false)); 84 } 85 86 SearchFilter *ExceptionSearchFilter::CreateFromStructuredData( 87 Target &target, const StructuredData::Dictionary &data_dict, 88 Status &error) { 89 SearchFilter *result = nullptr; 90 return result; 91 } 92 93 StructuredData::ObjectSP ExceptionSearchFilter::SerializeToStructuredData() { 94 StructuredData::ObjectSP result_sp; 95 96 return result_sp; 97 } 98 99 // The Target is the one that knows how to create breakpoints, so this function 100 // is meant to be used either by the target or internally in 101 // Set/ClearExceptionBreakpoints. 102 class ExceptionBreakpointResolver : public BreakpointResolver { 103 public: 104 ExceptionBreakpointResolver(lldb::LanguageType language, bool catch_bp, 105 bool throw_bp) 106 : BreakpointResolver(nullptr, BreakpointResolver::ExceptionResolver), 107 m_language(language), m_language_runtime(nullptr), m_catch_bp(catch_bp), 108 m_throw_bp(throw_bp) {} 109 110 ~ExceptionBreakpointResolver() override = default; 111 112 Searcher::CallbackReturn SearchCallback(SearchFilter &filter, 113 SymbolContext &context, 114 Address *addr) override { 115 116 if (SetActualResolver()) 117 return m_actual_resolver_sp->SearchCallback(filter, context, addr); 118 else 119 return eCallbackReturnStop; 120 } 121 122 lldb::SearchDepth GetDepth() override { 123 if (SetActualResolver()) 124 return m_actual_resolver_sp->GetDepth(); 125 else 126 return lldb::eSearchDepthTarget; 127 } 128 129 void GetDescription(Stream *s) override { 130 Language *language_plugin = Language::FindPlugin(m_language); 131 if (language_plugin) 132 language_plugin->GetExceptionResolverDescription(m_catch_bp, m_throw_bp, 133 *s); 134 else 135 Language::GetDefaultExceptionResolverDescription(m_catch_bp, m_throw_bp, 136 *s); 137 138 SetActualResolver(); 139 if (m_actual_resolver_sp) { 140 s->Printf(" using: "); 141 m_actual_resolver_sp->GetDescription(s); 142 } else 143 s->Printf(" the correct runtime exception handler will be determined " 144 "when you run"); 145 } 146 147 void Dump(Stream *s) const override {} 148 149 /// Methods for support type inquiry through isa, cast, and dyn_cast: 150 static inline bool classof(const BreakpointResolverName *) { return true; } 151 static inline bool classof(const BreakpointResolver *V) { 152 return V->getResolverID() == BreakpointResolver::ExceptionResolver; 153 } 154 155 protected: 156 BreakpointResolverSP CopyForBreakpoint(BreakpointSP &breakpoint) override { 157 BreakpointResolverSP ret_sp( 158 new ExceptionBreakpointResolver(m_language, m_catch_bp, m_throw_bp)); 159 ret_sp->SetBreakpoint(breakpoint); 160 return ret_sp; 161 } 162 163 bool SetActualResolver() { 164 BreakpointSP breakpoint_sp = GetBreakpoint(); 165 if (breakpoint_sp) { 166 ProcessSP process_sp = breakpoint_sp->GetTarget().GetProcessSP(); 167 if (process_sp) { 168 bool refreash_resolver = !m_actual_resolver_sp; 169 if (m_language_runtime == nullptr) { 170 m_language_runtime = process_sp->GetLanguageRuntime(m_language); 171 refreash_resolver = true; 172 } else { 173 LanguageRuntime *language_runtime = 174 process_sp->GetLanguageRuntime(m_language); 175 if (m_language_runtime != language_runtime) { 176 m_language_runtime = language_runtime; 177 refreash_resolver = true; 178 } 179 } 180 181 if (refreash_resolver && m_language_runtime) { 182 m_actual_resolver_sp = m_language_runtime->CreateExceptionResolver( 183 breakpoint_sp, m_catch_bp, m_throw_bp); 184 } 185 } else { 186 m_actual_resolver_sp.reset(); 187 m_language_runtime = nullptr; 188 } 189 } else { 190 m_actual_resolver_sp.reset(); 191 m_language_runtime = nullptr; 192 } 193 return (bool)m_actual_resolver_sp; 194 } 195 196 lldb::BreakpointResolverSP m_actual_resolver_sp; 197 lldb::LanguageType m_language; 198 LanguageRuntime *m_language_runtime; 199 bool m_catch_bp; 200 bool m_throw_bp; 201 }; 202 203 LanguageRuntime *LanguageRuntime::FindPlugin(Process *process, 204 lldb::LanguageType language) { 205 LanguageRuntimeCreateInstance create_callback; 206 for (uint32_t idx = 0; 207 (create_callback = 208 PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) != 209 nullptr; 210 ++idx) { 211 if (LanguageRuntime *runtime = create_callback(process, language)) 212 return runtime; 213 } 214 return nullptr; 215 } 216 217 LanguageRuntime::LanguageRuntime(Process *process) : Runtime(process) {} 218 219 BreakpointPreconditionSP 220 LanguageRuntime::GetExceptionPrecondition(LanguageType language, 221 bool throw_bp) { 222 LanguageRuntimeCreateInstance create_callback; 223 for (uint32_t idx = 0; 224 (create_callback = 225 PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) != 226 nullptr; 227 idx++) { 228 if (auto precondition_callback = 229 PluginManager::GetLanguageRuntimeGetExceptionPreconditionAtIndex( 230 idx)) { 231 if (BreakpointPreconditionSP precond = 232 precondition_callback(language, throw_bp)) 233 return precond; 234 } 235 } 236 return BreakpointPreconditionSP(); 237 } 238 239 BreakpointSP LanguageRuntime::CreateExceptionBreakpoint( 240 Target &target, lldb::LanguageType language, bool catch_bp, bool throw_bp, 241 bool is_internal) { 242 BreakpointResolverSP resolver_sp( 243 new ExceptionBreakpointResolver(language, catch_bp, throw_bp)); 244 SearchFilterSP filter_sp( 245 new ExceptionSearchFilter(target.shared_from_this(), language)); 246 bool hardware = false; 247 bool resolve_indirect_functions = false; 248 BreakpointSP exc_breakpt_sp( 249 target.CreateBreakpoint(filter_sp, resolver_sp, is_internal, hardware, 250 resolve_indirect_functions)); 251 if (exc_breakpt_sp) { 252 if (auto precond = GetExceptionPrecondition(language, throw_bp)) 253 exc_breakpt_sp->SetPrecondition(precond); 254 255 if (is_internal) 256 exc_breakpt_sp->SetBreakpointKind("exception"); 257 } 258 259 return exc_breakpt_sp; 260 } 261 262 UnwindPlanSP 263 LanguageRuntime::GetRuntimeUnwindPlan(Thread &thread, RegisterContext *regctx, 264 bool &behaves_like_zeroth_frame) { 265 ProcessSP process_sp = thread.GetProcess(); 266 if (!process_sp.get()) 267 return UnwindPlanSP(); 268 if (process_sp->GetDisableLangRuntimeUnwindPlans() == true) 269 return UnwindPlanSP(); 270 for (const lldb::LanguageType lang_type : Language::GetSupportedLanguages()) { 271 if (LanguageRuntime *runtime = process_sp->GetLanguageRuntime(lang_type)) { 272 UnwindPlanSP plan_sp = runtime->GetRuntimeUnwindPlan( 273 process_sp, regctx, behaves_like_zeroth_frame); 274 if (plan_sp.get()) 275 return plan_sp; 276 } 277 } 278 return UnwindPlanSP(); 279 } 280 281 void LanguageRuntime::InitializeCommands(CommandObject *parent) { 282 if (!parent) 283 return; 284 285 if (!parent->IsMultiwordObject()) 286 return; 287 288 LanguageRuntimeCreateInstance create_callback; 289 290 for (uint32_t idx = 0; 291 (create_callback = 292 PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) != 293 nullptr; 294 ++idx) { 295 if (LanguageRuntimeGetCommandObject command_callback = 296 PluginManager::GetLanguageRuntimeGetCommandObjectAtIndex(idx)) { 297 CommandObjectSP command = 298 command_callback(parent->GetCommandInterpreter()); 299 if (command) { 300 // the CommandObject vended by a Language plugin cannot be created once 301 // and cached because we may create multiple debuggers and need one 302 // instance of the command each - the implementing function is meant to 303 // create a new instance of the command each time it is invoked. 304 parent->LoadSubCommand(command->GetCommandName().str().c_str(), command); 305 } 306 } 307 } 308 } 309