blob: 8203c9efa76782657575a0bb244a6ba1853fdadf [file] [log] [blame]
Eugene Zelenko8f30a652015-10-23 18:39:37 +00001//===-- LanguageRuntime.cpp -------------------------------------*- C++ -*-===//
Jim Ingham22777012010-09-23 02:01:19 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Jim Ingham22777012010-09-23 02:01:19 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "lldb/Target/LanguageRuntime.h"
Jim Ingham0fcdac32015-11-06 22:48:59 +000010#include "Plugins/Language/ObjC/ObjCLanguage.h"
Jim Ingham22777012010-09-23 02:01:19 +000011#include "lldb/Core/PluginManager.h"
Jim Ingham33df7cd2014-12-06 01:28:03 +000012#include "lldb/Core/SearchFilter.h"
Colin Rileyc9c55a22015-05-04 18:39:38 +000013#include "lldb/Interpreter/CommandInterpreter.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000014#include "lldb/Target/ObjCLanguageRuntime.h"
15#include "lldb/Target/Target.h"
Jim Ingham22777012010-09-23 02:01:19 +000016
17using namespace lldb;
18using namespace lldb_private;
19
Jim Inghame14dc262016-09-12 23:10:56 +000020ExceptionSearchFilter::ExceptionSearchFilter(const lldb::TargetSP &target_sp,
21 lldb::LanguageType language,
22 bool update_module_list)
23 : SearchFilter(target_sp, FilterTy::Exception), m_language(language),
24 m_language_runtime(nullptr), m_filter_sp() {
25 if (update_module_list)
Kate Stoneb9c1b512016-09-06 20:57:50 +000026 UpdateModuleListIfNeeded();
Jim Inghame14dc262016-09-12 23:10:56 +000027}
Greg Claytonbff78252013-03-11 18:42:51 +000028
Jim Inghame14dc262016-09-12 23:10:56 +000029bool ExceptionSearchFilter::ModulePasses(const lldb::ModuleSP &module_sp) {
30 UpdateModuleListIfNeeded();
31 if (m_filter_sp)
32 return m_filter_sp->ModulePasses(module_sp);
33 return false;
34}
Kate Stoneb9c1b512016-09-06 20:57:50 +000035
Jim Inghame14dc262016-09-12 23:10:56 +000036bool ExceptionSearchFilter::ModulePasses(const FileSpec &spec) {
37 UpdateModuleListIfNeeded();
38 if (m_filter_sp)
39 return m_filter_sp->ModulePasses(spec);
40 return false;
41}
Kate Stoneb9c1b512016-09-06 20:57:50 +000042
Jim Inghame14dc262016-09-12 23:10:56 +000043void ExceptionSearchFilter::Search(Searcher &searcher) {
44 UpdateModuleListIfNeeded();
45 if (m_filter_sp)
46 m_filter_sp->Search(searcher);
47}
Kate Stoneb9c1b512016-09-06 20:57:50 +000048
Jim Inghame14dc262016-09-12 23:10:56 +000049void ExceptionSearchFilter::GetDescription(Stream *s) {
50 UpdateModuleListIfNeeded();
51 if (m_filter_sp)
52 m_filter_sp->GetDescription(s);
53}
Greg Claytonbff78252013-03-11 18:42:51 +000054
Jim Inghame14dc262016-09-12 23:10:56 +000055void ExceptionSearchFilter::UpdateModuleListIfNeeded() {
56 ProcessSP process_sp(m_target_sp->GetProcessSP());
57 if (process_sp) {
58 bool refreash_filter = !m_filter_sp;
59 if (m_language_runtime == nullptr) {
60 m_language_runtime = process_sp->GetLanguageRuntime(m_language);
61 refreash_filter = true;
Kate Stoneb9c1b512016-09-06 20:57:50 +000062 } else {
Jim Inghame14dc262016-09-12 23:10:56 +000063 LanguageRuntime *language_runtime =
64 process_sp->GetLanguageRuntime(m_language);
65 if (m_language_runtime != language_runtime) {
66 m_language_runtime = language_runtime;
67 refreash_filter = true;
68 }
Greg Claytonbff78252013-03-11 18:42:51 +000069 }
Jim Inghame14dc262016-09-12 23:10:56 +000070
71 if (refreash_filter && m_language_runtime) {
72 m_filter_sp = m_language_runtime->CreateExceptionSearchFilter();
73 }
74 } else {
75 m_filter_sp.reset();
76 m_language_runtime = nullptr;
Kate Stoneb9c1b512016-09-06 20:57:50 +000077 }
Jim Inghame14dc262016-09-12 23:10:56 +000078}
79
80SearchFilterSP
81ExceptionSearchFilter::DoCopyForBreakpoint(Breakpoint &breakpoint) {
82 return SearchFilterSP(
83 new ExceptionSearchFilter(TargetSP(), m_language, false));
84}
85
86SearchFilter *ExceptionSearchFilter::CreateFromStructuredData(
Zachary Turner97206d52017-05-12 04:51:55 +000087 Target &target, const StructuredData::Dictionary &data_dict,
88 Status &error) {
Jim Inghame14dc262016-09-12 23:10:56 +000089 SearchFilter *result = nullptr;
90 return result;
91}
92
93StructuredData::ObjectSP ExceptionSearchFilter::SerializeToStructuredData() {
94 StructuredData::ObjectSP result_sp;
95
96 return result_sp;
97}
Greg Claytonbff78252013-03-11 18:42:51 +000098
99// The Target is the one that knows how to create breakpoints, so this function
Kate Stoneb9c1b512016-09-06 20:57:50 +0000100// is meant to be used either by the target or internally in
101// Set/ClearExceptionBreakpoints.
102class ExceptionBreakpointResolver : public BreakpointResolver {
Greg Claytonbff78252013-03-11 18:42:51 +0000103public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000104 ExceptionBreakpointResolver(lldb::LanguageType language, bool catch_bp,
105 bool throw_bp)
106 : BreakpointResolver(nullptr, BreakpointResolver::ExceptionResolver),
107 m_language(language), m_language_runtime(nullptr), m_catch_bp(catch_bp),
108 m_throw_bp(throw_bp) {}
Greg Claytonbff78252013-03-11 18:42:51 +0000109
Kate Stoneb9c1b512016-09-06 20:57:50 +0000110 ~ExceptionBreakpointResolver() override = default;
Eugene Zelenko8f30a652015-10-23 18:39:37 +0000111
Kate Stoneb9c1b512016-09-06 20:57:50 +0000112 Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
113 SymbolContext &context, Address *addr,
114 bool containing) override {
Greg Claytonbff78252013-03-11 18:42:51 +0000115
Kate Stoneb9c1b512016-09-06 20:57:50 +0000116 if (SetActualResolver())
117 return m_actual_resolver_sp->SearchCallback(filter, context, addr,
118 containing);
119 else
120 return eCallbackReturnStop;
121 }
122
Jim Ingham4911d362018-09-07 18:43:04 +0000123 lldb::SearchDepth GetDepth() override {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000124 if (SetActualResolver())
125 return m_actual_resolver_sp->GetDepth();
126 else
Jim Ingham4911d362018-09-07 18:43:04 +0000127 return lldb::eSearchDepthTarget;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000128 }
129
130 void GetDescription(Stream *s) override {
131 Language *language_plugin = Language::FindPlugin(m_language);
132 if (language_plugin)
133 language_plugin->GetExceptionResolverDescription(m_catch_bp, m_throw_bp,
134 *s);
135 else
136 Language::GetDefaultExceptionResolverDescription(m_catch_bp, m_throw_bp,
137 *s);
138
139 SetActualResolver();
140 if (m_actual_resolver_sp) {
141 s->Printf(" using: ");
142 m_actual_resolver_sp->GetDescription(s);
143 } else
144 s->Printf(" the correct runtime exception handler will be determined "
145 "when you run");
146 }
147
148 void Dump(Stream *s) const override {}
149
150 /// Methods for support type inquiry through isa, cast, and dyn_cast:
151 static inline bool classof(const BreakpointResolverName *) { return true; }
152 static inline bool classof(const BreakpointResolver *V) {
153 return V->getResolverID() == BreakpointResolver::ExceptionResolver;
154 }
Eugene Zelenko8f30a652015-10-23 18:39:37 +0000155
Greg Claytonbff78252013-03-11 18:42:51 +0000156protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000157 BreakpointResolverSP CopyForBreakpoint(Breakpoint &breakpoint) override {
158 return BreakpointResolverSP(
159 new ExceptionBreakpointResolver(m_language, m_catch_bp, m_throw_bp));
160 }
Jim Ingham33df7cd2014-12-06 01:28:03 +0000161
Kate Stoneb9c1b512016-09-06 20:57:50 +0000162 bool SetActualResolver() {
163 ProcessSP process_sp;
164 if (m_breakpoint) {
165 process_sp = m_breakpoint->GetTarget().GetProcessSP();
166 if (process_sp) {
167 bool refreash_resolver = !m_actual_resolver_sp;
168 if (m_language_runtime == nullptr) {
169 m_language_runtime = process_sp->GetLanguageRuntime(m_language);
170 refreash_resolver = true;
171 } else {
172 LanguageRuntime *language_runtime =
173 process_sp->GetLanguageRuntime(m_language);
174 if (m_language_runtime != language_runtime) {
175 m_language_runtime = language_runtime;
176 refreash_resolver = true;
177 }
Greg Claytonbff78252013-03-11 18:42:51 +0000178 }
Eugene Zelenko9394d7722016-02-18 00:10:17 +0000179
Kate Stoneb9c1b512016-09-06 20:57:50 +0000180 if (refreash_resolver && m_language_runtime) {
181 m_actual_resolver_sp = m_language_runtime->CreateExceptionResolver(
182 m_breakpoint, m_catch_bp, m_throw_bp);
183 }
184 } else {
185 m_actual_resolver_sp.reset();
186 m_language_runtime = nullptr;
187 }
188 } else {
189 m_actual_resolver_sp.reset();
190 m_language_runtime = nullptr;
191 }
192 return (bool)m_actual_resolver_sp;
193 }
194
195 lldb::BreakpointResolverSP m_actual_resolver_sp;
196 lldb::LanguageType m_language;
197 LanguageRuntime *m_language_runtime;
198 bool m_catch_bp;
199 bool m_throw_bp;
Greg Claytonbff78252013-03-11 18:42:51 +0000200};
201
Kate Stoneb9c1b512016-09-06 20:57:50 +0000202LanguageRuntime *LanguageRuntime::FindPlugin(Process *process,
203 lldb::LanguageType language) {
204 std::unique_ptr<LanguageRuntime> language_runtime_ap;
205 LanguageRuntimeCreateInstance create_callback;
Jim Ingham22777012010-09-23 02:01:19 +0000206
Kate Stoneb9c1b512016-09-06 20:57:50 +0000207 for (uint32_t idx = 0;
208 (create_callback =
209 PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) !=
210 nullptr;
211 ++idx) {
212 language_runtime_ap.reset(create_callback(process, language));
Jim Ingham22777012010-09-23 02:01:19 +0000213
Kate Stoneb9c1b512016-09-06 20:57:50 +0000214 if (language_runtime_ap)
215 return language_runtime_ap.release();
216 }
Jim Ingham22777012010-09-23 02:01:19 +0000217
Kate Stoneb9c1b512016-09-06 20:57:50 +0000218 return nullptr;
Jim Ingham22777012010-09-23 02:01:19 +0000219}
220
Kate Stoneb9c1b512016-09-06 20:57:50 +0000221LanguageRuntime::LanguageRuntime(Process *process) : m_process(process) {}
Jim Ingham22777012010-09-23 02:01:19 +0000222
Eugene Zelenko8f30a652015-10-23 18:39:37 +0000223LanguageRuntime::~LanguageRuntime() = default;
Jim Ingham219ba192012-03-05 04:47:34 +0000224
Jim Inghama72b31c2015-04-22 19:42:18 +0000225Breakpoint::BreakpointPreconditionSP
Kate Stoneb9c1b512016-09-06 20:57:50 +0000226LanguageRuntime::CreateExceptionPrecondition(lldb::LanguageType language,
227 bool catch_bp, bool throw_bp) {
228 switch (language) {
229 case eLanguageTypeObjC:
230 if (throw_bp)
231 return Breakpoint::BreakpointPreconditionSP(
232 new ObjCLanguageRuntime::ObjCExceptionPrecondition());
233 break;
234 default:
235 break;
236 }
237 return Breakpoint::BreakpointPreconditionSP();
Jim Inghama72b31c2015-04-22 19:42:18 +0000238}
239
Kate Stoneb9c1b512016-09-06 20:57:50 +0000240BreakpointSP LanguageRuntime::CreateExceptionBreakpoint(
241 Target &target, lldb::LanguageType language, bool catch_bp, bool throw_bp,
242 bool is_internal) {
243 BreakpointResolverSP resolver_sp(
244 new ExceptionBreakpointResolver(language, catch_bp, throw_bp));
245 SearchFilterSP filter_sp(
246 new ExceptionSearchFilter(target.shared_from_this(), language));
247 bool hardware = false;
248 bool resolve_indirect_functions = false;
249 BreakpointSP exc_breakpt_sp(
250 target.CreateBreakpoint(filter_sp, resolver_sp, is_internal, hardware,
251 resolve_indirect_functions));
252 if (exc_breakpt_sp) {
253 Breakpoint::BreakpointPreconditionSP precondition_sp =
254 CreateExceptionPrecondition(language, catch_bp, throw_bp);
255 if (precondition_sp)
256 exc_breakpt_sp->SetPrecondition(precondition_sp);
Jim Inghama72b31c2015-04-22 19:42:18 +0000257
Kate Stoneb9c1b512016-09-06 20:57:50 +0000258 if (is_internal)
259 exc_breakpt_sp->SetBreakpointKind("exception");
260 }
261
262 return exc_breakpt_sp;
Jim Ingham219ba192012-03-05 04:47:34 +0000263}
264
Kate Stoneb9c1b512016-09-06 20:57:50 +0000265void LanguageRuntime::InitializeCommands(CommandObject *parent) {
266 if (!parent)
267 return;
Colin Rileyc9c55a22015-05-04 18:39:38 +0000268
Kate Stoneb9c1b512016-09-06 20:57:50 +0000269 if (!parent->IsMultiwordObject())
270 return;
Colin Rileyc9c55a22015-05-04 18:39:38 +0000271
Kate Stoneb9c1b512016-09-06 20:57:50 +0000272 LanguageRuntimeCreateInstance create_callback;
Colin Rileyc9c55a22015-05-04 18:39:38 +0000273
Kate Stoneb9c1b512016-09-06 20:57:50 +0000274 for (uint32_t idx = 0;
275 (create_callback =
276 PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) !=
277 nullptr;
278 ++idx) {
279 if (LanguageRuntimeGetCommandObject command_callback =
280 PluginManager::GetLanguageRuntimeGetCommandObjectAtIndex(idx)) {
281 CommandObjectSP command =
282 command_callback(parent->GetCommandInterpreter());
283 if (command) {
284 // the CommandObject vended by a Language plugin cannot be created once
Zachary Turnera4496982016-10-05 21:14:38 +0000285 // and cached because we may create multiple debuggers and need one
286 // instance of the command each - the implementing function is meant to
287 // create a new instance of the command each time it is invoked.
288 parent->LoadSubCommand(command->GetCommandName().str().c_str(), command);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000289 }
Colin Rileyc9c55a22015-05-04 18:39:38 +0000290 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000291 }
Colin Rileyc9c55a22015-05-04 18:39:38 +0000292}
293
Kate Stoneb9c1b512016-09-06 20:57:50 +0000294lldb::SearchFilterSP LanguageRuntime::CreateExceptionSearchFilter() {
295 return m_process->GetTarget().GetSearchFilterForModule(nullptr);
Greg Claytonbff78252013-03-11 18:42:51 +0000296}