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