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