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 "lldb/Target/ObjCLanguageRuntime.h" 16 #include "lldb/Target/Target.h" 17 #include "lldb/Core/PluginManager.h" 18 #include "lldb/Core/SearchFilter.h" 19 #include "lldb/Interpreter/CommandInterpreter.h" 20 21 using namespace lldb; 22 using namespace lldb_private; 23 24 class ExceptionSearchFilter : public SearchFilter 25 { 26 public: 27 ExceptionSearchFilter (const lldb::TargetSP &target_sp, 28 lldb::LanguageType language, 29 bool update_module_list = true) : 30 SearchFilter (target_sp), 31 m_language (language), 32 m_language_runtime (NULL), 33 m_filter_sp () 34 { 35 if (update_module_list) 36 UpdateModuleListIfNeeded (); 37 } 38 39 ~ExceptionSearchFilter() override = default; 40 41 bool 42 ModulePasses (const lldb::ModuleSP &module_sp) override 43 { 44 UpdateModuleListIfNeeded (); 45 if (m_filter_sp) 46 return m_filter_sp->ModulePasses (module_sp); 47 return false; 48 } 49 50 bool 51 ModulePasses (const FileSpec &spec) override 52 { 53 UpdateModuleListIfNeeded (); 54 if (m_filter_sp) 55 return m_filter_sp->ModulePasses (spec); 56 return false; 57 } 58 59 void 60 Search (Searcher &searcher) override 61 { 62 UpdateModuleListIfNeeded (); 63 if (m_filter_sp) 64 m_filter_sp->Search (searcher); 65 } 66 67 void 68 GetDescription (Stream *s) override 69 { 70 UpdateModuleListIfNeeded (); 71 if (m_filter_sp) 72 m_filter_sp->GetDescription (s); 73 } 74 75 protected: 76 LanguageType m_language; 77 LanguageRuntime *m_language_runtime; 78 SearchFilterSP m_filter_sp; 79 80 SearchFilterSP 81 DoCopyForBreakpoint(Breakpoint &breakpoint) override 82 { 83 return SearchFilterSP(new ExceptionSearchFilter(TargetSP(), m_language, false)); 84 } 85 86 void 87 UpdateModuleListIfNeeded () 88 { 89 ProcessSP process_sp (m_target_sp->GetProcessSP()); 90 if (process_sp) 91 { 92 bool refreash_filter = !m_filter_sp; 93 if (m_language_runtime == NULL) 94 { 95 m_language_runtime = process_sp->GetLanguageRuntime(m_language); 96 refreash_filter = true; 97 } 98 else 99 { 100 LanguageRuntime *language_runtime = process_sp->GetLanguageRuntime(m_language); 101 if (m_language_runtime != language_runtime) 102 { 103 m_language_runtime = language_runtime; 104 refreash_filter = true; 105 } 106 } 107 108 if (refreash_filter && m_language_runtime) 109 { 110 m_filter_sp = m_language_runtime->CreateExceptionSearchFilter (); 111 } 112 } 113 else 114 { 115 m_filter_sp.reset(); 116 m_language_runtime = NULL; 117 } 118 } 119 }; 120 121 // The Target is the one that knows how to create breakpoints, so this function 122 // is meant to be used either by the target or internally in Set/ClearExceptionBreakpoints. 123 class ExceptionBreakpointResolver : public BreakpointResolver 124 { 125 public: 126 ExceptionBreakpointResolver (lldb::LanguageType language, 127 bool catch_bp, 128 bool throw_bp) : 129 BreakpointResolver (NULL, BreakpointResolver::ExceptionResolver), 130 m_language (language), 131 m_language_runtime (NULL), 132 m_catch_bp (catch_bp), 133 m_throw_bp (throw_bp) 134 { 135 } 136 137 ~ExceptionBreakpointResolver() override = default; 138 139 Searcher::CallbackReturn 140 SearchCallback (SearchFilter &filter, 141 SymbolContext &context, 142 Address *addr, 143 bool containing) override 144 { 145 146 if (SetActualResolver()) 147 return m_actual_resolver_sp->SearchCallback (filter, context, addr, containing); 148 else 149 return eCallbackReturnStop; 150 } 151 152 Searcher::Depth 153 GetDepth () override 154 { 155 if (SetActualResolver()) 156 return m_actual_resolver_sp->GetDepth(); 157 else 158 return eDepthTarget; 159 } 160 161 void 162 GetDescription (Stream *s) override 163 { 164 s->Printf ("Exception breakpoint (catch: %s throw: %s)", 165 m_catch_bp ? "on" : "off", 166 m_throw_bp ? "on" : "off"); 167 168 SetActualResolver(); 169 if (m_actual_resolver_sp) 170 { 171 s->Printf (" using: "); 172 m_actual_resolver_sp->GetDescription (s); 173 } 174 else 175 s->Printf (" the correct runtime exception handler will be determined when you run"); 176 } 177 178 void 179 Dump (Stream *s) const override 180 { 181 } 182 183 /// Methods for support type inquiry through isa, cast, and dyn_cast: 184 static inline bool classof(const BreakpointResolverName *) { return true; } 185 static inline bool classof(const BreakpointResolver *V) { 186 return V->getResolverID() == BreakpointResolver::ExceptionResolver; 187 } 188 189 protected: 190 BreakpointResolverSP 191 CopyForBreakpoint (Breakpoint &breakpoint) override 192 { 193 return BreakpointResolverSP(new ExceptionBreakpointResolver(m_language, m_catch_bp, m_throw_bp)); 194 } 195 196 bool 197 SetActualResolver() 198 { 199 ProcessSP process_sp; 200 if (m_breakpoint) 201 { 202 process_sp = m_breakpoint->GetTarget().GetProcessSP(); 203 if (process_sp) 204 { 205 bool refreash_resolver = !m_actual_resolver_sp; 206 if (m_language_runtime == NULL) 207 { 208 m_language_runtime = process_sp->GetLanguageRuntime(m_language); 209 refreash_resolver = true; 210 } 211 else 212 { 213 LanguageRuntime *language_runtime = process_sp->GetLanguageRuntime(m_language); 214 if (m_language_runtime != language_runtime) 215 { 216 m_language_runtime = language_runtime; 217 refreash_resolver = true; 218 } 219 } 220 221 if (refreash_resolver && m_language_runtime) 222 { 223 m_actual_resolver_sp = m_language_runtime->CreateExceptionResolver (m_breakpoint, m_catch_bp, m_throw_bp); 224 } 225 } 226 else 227 { 228 m_actual_resolver_sp.reset(); 229 m_language_runtime = NULL; 230 } 231 } 232 else 233 { 234 m_actual_resolver_sp.reset(); 235 m_language_runtime = NULL; 236 } 237 return (bool)m_actual_resolver_sp; 238 } 239 lldb::BreakpointResolverSP m_actual_resolver_sp; 240 lldb::LanguageType m_language; 241 LanguageRuntime *m_language_runtime; 242 bool m_catch_bp; 243 bool m_throw_bp; 244 }; 245 246 LanguageRuntime* 247 LanguageRuntime::FindPlugin (Process *process, lldb::LanguageType language) 248 { 249 std::unique_ptr<LanguageRuntime> language_runtime_ap; 250 LanguageRuntimeCreateInstance create_callback; 251 252 for (uint32_t idx = 0; 253 (create_callback = PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) != NULL; 254 ++idx) 255 { 256 language_runtime_ap.reset (create_callback(process, language)); 257 258 if (language_runtime_ap.get()) 259 return language_runtime_ap.release(); 260 } 261 262 return NULL; 263 } 264 265 LanguageRuntime::LanguageRuntime(Process *process) : 266 m_process (process) 267 { 268 } 269 270 LanguageRuntime::~LanguageRuntime() = default; 271 272 Breakpoint::BreakpointPreconditionSP 273 LanguageRuntime::CreateExceptionPrecondition (lldb::LanguageType language, 274 bool catch_bp, 275 bool throw_bp) 276 { 277 switch (language) 278 { 279 case eLanguageTypeObjC: 280 if (throw_bp) 281 return Breakpoint::BreakpointPreconditionSP(new ObjCLanguageRuntime::ObjCExceptionPrecondition ()); 282 break; 283 default: 284 break; 285 } 286 return Breakpoint::BreakpointPreconditionSP(); 287 } 288 289 BreakpointSP 290 LanguageRuntime::CreateExceptionBreakpoint (Target &target, 291 lldb::LanguageType language, 292 bool catch_bp, 293 bool throw_bp, 294 bool is_internal) 295 { 296 BreakpointResolverSP resolver_sp(new ExceptionBreakpointResolver(language, catch_bp, throw_bp)); 297 SearchFilterSP filter_sp(new ExceptionSearchFilter(target.shared_from_this(), language)); 298 bool hardware = false; 299 bool resolve_indirect_functions = false; 300 BreakpointSP exc_breakpt_sp (target.CreateBreakpoint (filter_sp, resolver_sp, is_internal, hardware, resolve_indirect_functions)); 301 if (exc_breakpt_sp) 302 { 303 Breakpoint::BreakpointPreconditionSP precondition_sp = CreateExceptionPrecondition(language, catch_bp, throw_bp); 304 if (precondition_sp) 305 exc_breakpt_sp->SetPrecondition(precondition_sp); 306 307 if (is_internal) 308 exc_breakpt_sp->SetBreakpointKind("exception"); 309 } 310 311 return exc_breakpt_sp; 312 } 313 314 void 315 LanguageRuntime::InitializeCommands (CommandObject* parent) 316 { 317 if (!parent) 318 return; 319 320 if (!parent->IsMultiwordObject()) 321 return; 322 323 LanguageRuntimeCreateInstance create_callback; 324 325 for (uint32_t idx = 0; 326 (create_callback = PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) != nullptr; 327 ++idx) 328 { 329 if (LanguageRuntimeGetCommandObject command_callback = 330 PluginManager::GetLanguageRuntimeGetCommandObjectAtIndex(idx)) 331 { 332 CommandObjectSP command = command_callback(parent->GetCommandInterpreter()); 333 if (command) 334 { 335 parent->LoadSubCommand(command->GetCommandName(), command); 336 } 337 } 338 } 339 } 340 341 lldb::SearchFilterSP 342 LanguageRuntime::CreateExceptionSearchFilter () 343 { 344 return m_process->GetTarget().GetSearchFilterForModule(NULL); 345 } 346