1 //===-- LanguageRuntime.cpp -------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/Target/LanguageRuntime.h"
11 #include "Plugins/Language/ObjC/ObjCLanguage.h"
12 #include "lldb/Core/PluginManager.h"
13 #include "lldb/Core/SearchFilter.h"
14 #include "lldb/Interpreter/CommandInterpreter.h"
15 #include "lldb/Target/ObjCLanguageRuntime.h"
16 #include "lldb/Target/Target.h"
19 using namespace lldb_private;
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();
30 bool ExceptionSearchFilter::ModulePasses(const lldb::ModuleSP &module_sp) {
31 UpdateModuleListIfNeeded();
33 return m_filter_sp->ModulePasses(module_sp);
37 bool ExceptionSearchFilter::ModulePasses(const FileSpec &spec) {
38 UpdateModuleListIfNeeded();
40 return m_filter_sp->ModulePasses(spec);
44 void ExceptionSearchFilter::Search(Searcher &searcher) {
45 UpdateModuleListIfNeeded();
47 m_filter_sp->Search(searcher);
50 void ExceptionSearchFilter::GetDescription(Stream *s) {
51 UpdateModuleListIfNeeded();
53 m_filter_sp->GetDescription(s);
56 void ExceptionSearchFilter::UpdateModuleListIfNeeded() {
57 ProcessSP process_sp(m_target_sp->GetProcessSP());
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;
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;
72 if (refreash_filter && m_language_runtime) {
73 m_filter_sp = m_language_runtime->CreateExceptionSearchFilter();
77 m_language_runtime = nullptr;
82 ExceptionSearchFilter::DoCopyForBreakpoint(Breakpoint &breakpoint) {
83 return SearchFilterSP(
84 new ExceptionSearchFilter(TargetSP(), m_language, false));
87 SearchFilter *ExceptionSearchFilter::CreateFromStructuredData(
88 Target &target, const StructuredData::Dictionary &data_dict,
90 SearchFilter *result = nullptr;
94 StructuredData::ObjectSP ExceptionSearchFilter::SerializeToStructuredData() {
95 StructuredData::ObjectSP result_sp;
100 // The Target is the one that knows how to create breakpoints, so this function
101 // is meant to be used either by the target or internally in
102 // Set/ClearExceptionBreakpoints.
103 class ExceptionBreakpointResolver : public BreakpointResolver {
105 ExceptionBreakpointResolver(lldb::LanguageType language, bool catch_bp,
107 : BreakpointResolver(nullptr, BreakpointResolver::ExceptionResolver),
108 m_language(language), m_language_runtime(nullptr), m_catch_bp(catch_bp),
109 m_throw_bp(throw_bp) {}
111 ~ExceptionBreakpointResolver() override = default;
113 Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
114 SymbolContext &context, Address *addr,
115 bool containing) override {
117 if (SetActualResolver())
118 return m_actual_resolver_sp->SearchCallback(filter, context, addr,
121 return eCallbackReturnStop;
124 lldb::SearchDepth GetDepth() override {
125 if (SetActualResolver())
126 return m_actual_resolver_sp->GetDepth();
128 return lldb::eSearchDepthTarget;
131 void GetDescription(Stream *s) override {
132 Language *language_plugin = Language::FindPlugin(m_language);
134 language_plugin->GetExceptionResolverDescription(m_catch_bp, m_throw_bp,
137 Language::GetDefaultExceptionResolverDescription(m_catch_bp, m_throw_bp,
141 if (m_actual_resolver_sp) {
142 s->Printf(" using: ");
143 m_actual_resolver_sp->GetDescription(s);
145 s->Printf(" the correct runtime exception handler will be determined "
149 void Dump(Stream *s) const override {}
151 /// Methods for support type inquiry through isa, cast, and dyn_cast:
152 static inline bool classof(const BreakpointResolverName *) { return true; }
153 static inline bool classof(const BreakpointResolver *V) {
154 return V->getResolverID() == BreakpointResolver::ExceptionResolver;
158 BreakpointResolverSP CopyForBreakpoint(Breakpoint &breakpoint) override {
159 return BreakpointResolverSP(
160 new ExceptionBreakpointResolver(m_language, m_catch_bp, m_throw_bp));
163 bool SetActualResolver() {
164 ProcessSP process_sp;
166 process_sp = m_breakpoint->GetTarget().GetProcessSP();
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;
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;
181 if (refreash_resolver && m_language_runtime) {
182 m_actual_resolver_sp = m_language_runtime->CreateExceptionResolver(
183 m_breakpoint, m_catch_bp, m_throw_bp);
186 m_actual_resolver_sp.reset();
187 m_language_runtime = nullptr;
190 m_actual_resolver_sp.reset();
191 m_language_runtime = nullptr;
193 return (bool)m_actual_resolver_sp;
196 lldb::BreakpointResolverSP m_actual_resolver_sp;
197 lldb::LanguageType m_language;
198 LanguageRuntime *m_language_runtime;
203 LanguageRuntime *LanguageRuntime::FindPlugin(Process *process,
204 lldb::LanguageType language) {
205 std::unique_ptr<LanguageRuntime> language_runtime_ap;
206 LanguageRuntimeCreateInstance create_callback;
208 for (uint32_t idx = 0;
210 PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) !=
213 language_runtime_ap.reset(create_callback(process, language));
215 if (language_runtime_ap)
216 return language_runtime_ap.release();
222 LanguageRuntime::LanguageRuntime(Process *process) : m_process(process) {}
224 LanguageRuntime::~LanguageRuntime() = default;
226 Breakpoint::BreakpointPreconditionSP
227 LanguageRuntime::CreateExceptionPrecondition(lldb::LanguageType language,
228 bool catch_bp, bool throw_bp) {
230 case eLanguageTypeObjC:
232 return Breakpoint::BreakpointPreconditionSP(
233 new ObjCLanguageRuntime::ObjCExceptionPrecondition());
238 return Breakpoint::BreakpointPreconditionSP();
241 BreakpointSP LanguageRuntime::CreateExceptionBreakpoint(
242 Target &target, lldb::LanguageType language, bool catch_bp, bool throw_bp,
244 BreakpointResolverSP resolver_sp(
245 new ExceptionBreakpointResolver(language, catch_bp, throw_bp));
246 SearchFilterSP filter_sp(
247 new ExceptionSearchFilter(target.shared_from_this(), language));
248 bool hardware = false;
249 bool resolve_indirect_functions = false;
250 BreakpointSP exc_breakpt_sp(
251 target.CreateBreakpoint(filter_sp, resolver_sp, is_internal, hardware,
252 resolve_indirect_functions));
253 if (exc_breakpt_sp) {
254 Breakpoint::BreakpointPreconditionSP precondition_sp =
255 CreateExceptionPrecondition(language, catch_bp, throw_bp);
257 exc_breakpt_sp->SetPrecondition(precondition_sp);
260 exc_breakpt_sp->SetBreakpointKind("exception");
263 return exc_breakpt_sp;
266 void LanguageRuntime::InitializeCommands(CommandObject *parent) {
270 if (!parent->IsMultiwordObject())
273 LanguageRuntimeCreateInstance create_callback;
275 for (uint32_t idx = 0;
277 PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) !=
280 if (LanguageRuntimeGetCommandObject command_callback =
281 PluginManager::GetLanguageRuntimeGetCommandObjectAtIndex(idx)) {
282 CommandObjectSP command =
283 command_callback(parent->GetCommandInterpreter());
285 // the CommandObject vended by a Language plugin cannot be created once
286 // and cached because we may create multiple debuggers and need one
287 // instance of the command each - the implementing function is meant to
288 // create a new instance of the command each time it is invoked.
289 parent->LoadSubCommand(command->GetCommandName().str().c_str(), command);
295 lldb::SearchFilterSP LanguageRuntime::CreateExceptionSearchFilter() {
296 return m_process->GetTarget().GetSearchFilterForModule(nullptr);