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 //===----------------------------------------------------------------------===//
12 // Other libraries and framework includes
14 #include "lldb/Target/LanguageRuntime.h"
15 #include "Plugins/Language/ObjC/ObjCLanguage.h"
16 #include "lldb/Core/PluginManager.h"
17 #include "lldb/Core/SearchFilter.h"
18 #include "lldb/Interpreter/CommandInterpreter.h"
19 #include "lldb/Target/ObjCLanguageRuntime.h"
20 #include "lldb/Target/Target.h"
23 using namespace lldb_private;
25 ExceptionSearchFilter::ExceptionSearchFilter(const lldb::TargetSP &target_sp,
26 lldb::LanguageType language,
27 bool update_module_list)
28 : SearchFilter(target_sp, FilterTy::Exception), m_language(language),
29 m_language_runtime(nullptr), m_filter_sp() {
30 if (update_module_list)
31 UpdateModuleListIfNeeded();
34 bool ExceptionSearchFilter::ModulePasses(const lldb::ModuleSP &module_sp) {
35 UpdateModuleListIfNeeded();
37 return m_filter_sp->ModulePasses(module_sp);
41 bool ExceptionSearchFilter::ModulePasses(const FileSpec &spec) {
42 UpdateModuleListIfNeeded();
44 return m_filter_sp->ModulePasses(spec);
48 void ExceptionSearchFilter::Search(Searcher &searcher) {
49 UpdateModuleListIfNeeded();
51 m_filter_sp->Search(searcher);
54 void ExceptionSearchFilter::GetDescription(Stream *s) {
55 UpdateModuleListIfNeeded();
57 m_filter_sp->GetDescription(s);
60 void ExceptionSearchFilter::UpdateModuleListIfNeeded() {
61 ProcessSP process_sp(m_target_sp->GetProcessSP());
63 bool refreash_filter = !m_filter_sp;
64 if (m_language_runtime == nullptr) {
65 m_language_runtime = process_sp->GetLanguageRuntime(m_language);
66 refreash_filter = true;
68 LanguageRuntime *language_runtime =
69 process_sp->GetLanguageRuntime(m_language);
70 if (m_language_runtime != language_runtime) {
71 m_language_runtime = language_runtime;
72 refreash_filter = true;
76 if (refreash_filter && m_language_runtime) {
77 m_filter_sp = m_language_runtime->CreateExceptionSearchFilter();
81 m_language_runtime = nullptr;
86 ExceptionSearchFilter::DoCopyForBreakpoint(Breakpoint &breakpoint) {
87 return SearchFilterSP(
88 new ExceptionSearchFilter(TargetSP(), m_language, false));
91 SearchFilter *ExceptionSearchFilter::CreateFromStructuredData(
92 Target &target, const StructuredData::Dictionary &data_dict,
94 SearchFilter *result = nullptr;
98 StructuredData::ObjectSP ExceptionSearchFilter::SerializeToStructuredData() {
99 StructuredData::ObjectSP result_sp;
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 {
109 ExceptionBreakpointResolver(lldb::LanguageType language, bool catch_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) {}
115 ~ExceptionBreakpointResolver() override = default;
117 Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
118 SymbolContext &context, Address *addr,
119 bool containing) override {
121 if (SetActualResolver())
122 return m_actual_resolver_sp->SearchCallback(filter, context, addr,
125 return eCallbackReturnStop;
128 Searcher::Depth GetDepth() override {
129 if (SetActualResolver())
130 return m_actual_resolver_sp->GetDepth();
135 void GetDescription(Stream *s) override {
136 Language *language_plugin = Language::FindPlugin(m_language);
138 language_plugin->GetExceptionResolverDescription(m_catch_bp, m_throw_bp,
141 Language::GetDefaultExceptionResolverDescription(m_catch_bp, m_throw_bp,
145 if (m_actual_resolver_sp) {
146 s->Printf(" using: ");
147 m_actual_resolver_sp->GetDescription(s);
149 s->Printf(" the correct runtime exception handler will be determined "
153 void Dump(Stream *s) const override {}
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;
162 BreakpointResolverSP CopyForBreakpoint(Breakpoint &breakpoint) override {
163 return BreakpointResolverSP(
164 new ExceptionBreakpointResolver(m_language, m_catch_bp, m_throw_bp));
167 bool SetActualResolver() {
168 ProcessSP process_sp;
170 process_sp = m_breakpoint->GetTarget().GetProcessSP();
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;
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;
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);
190 m_actual_resolver_sp.reset();
191 m_language_runtime = nullptr;
194 m_actual_resolver_sp.reset();
195 m_language_runtime = nullptr;
197 return (bool)m_actual_resolver_sp;
200 lldb::BreakpointResolverSP m_actual_resolver_sp;
201 lldb::LanguageType m_language;
202 LanguageRuntime *m_language_runtime;
207 LanguageRuntime *LanguageRuntime::FindPlugin(Process *process,
208 lldb::LanguageType language) {
209 std::unique_ptr<LanguageRuntime> language_runtime_ap;
210 LanguageRuntimeCreateInstance create_callback;
212 for (uint32_t idx = 0;
214 PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) !=
217 language_runtime_ap.reset(create_callback(process, language));
219 if (language_runtime_ap)
220 return language_runtime_ap.release();
226 LanguageRuntime::LanguageRuntime(Process *process) : m_process(process) {}
228 LanguageRuntime::~LanguageRuntime() = default;
230 Breakpoint::BreakpointPreconditionSP
231 LanguageRuntime::CreateExceptionPrecondition(lldb::LanguageType language,
232 bool catch_bp, bool throw_bp) {
234 case eLanguageTypeObjC:
236 return Breakpoint::BreakpointPreconditionSP(
237 new ObjCLanguageRuntime::ObjCExceptionPrecondition());
242 return Breakpoint::BreakpointPreconditionSP();
245 BreakpointSP LanguageRuntime::CreateExceptionBreakpoint(
246 Target &target, lldb::LanguageType language, bool catch_bp, bool throw_bp,
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);
261 exc_breakpt_sp->SetPrecondition(precondition_sp);
264 exc_breakpt_sp->SetBreakpointKind("exception");
267 return exc_breakpt_sp;
270 void LanguageRuntime::InitializeCommands(CommandObject *parent) {
274 if (!parent->IsMultiwordObject())
277 LanguageRuntimeCreateInstance create_callback;
279 for (uint32_t idx = 0;
281 PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) !=
284 if (LanguageRuntimeGetCommandObject command_callback =
285 PluginManager::GetLanguageRuntimeGetCommandObjectAtIndex(idx)) {
286 CommandObjectSP command =
287 command_callback(parent->GetCommandInterpreter());
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);
299 lldb::SearchFilterSP LanguageRuntime::CreateExceptionSearchFilter() {
300 return m_process->GetTarget().GetSearchFilterForModule(nullptr);