1//===-- ScriptInterpreter.h -------------------------------------*- C++ -*-===//
2//
3// 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
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLDB_INTERPRETER_SCRIPTINTERPRETER_H
10#define LLDB_INTERPRETER_SCRIPTINTERPRETER_H
11
12#include "lldb/API/SBData.h"
13#include "lldb/API/SBError.h"
14#include "lldb/Breakpoint/BreakpointOptions.h"
15#include "lldb/Core/Communication.h"
16#include "lldb/Core/PluginInterface.h"
17#include "lldb/Core/SearchFilter.h"
18#include "lldb/Core/StreamFile.h"
19#include "lldb/Host/PseudoTerminal.h"
20#include "lldb/Interpreter/ScriptedProcessInterface.h"
21#include "lldb/Utility/Broadcaster.h"
22#include "lldb/Utility/Status.h"
23#include "lldb/Utility/StructuredData.h"
24#include "lldb/lldb-private.h"
25
26namespace lldb_private {
27
28class ScriptInterpreterLocker {
29public:
30 ScriptInterpreterLocker() = default;
31
32 virtual ~ScriptInterpreterLocker() = default;
33
34private:
35 ScriptInterpreterLocker(const ScriptInterpreterLocker &) = delete;
36 const ScriptInterpreterLocker &
37 operator=(const ScriptInterpreterLocker &) = delete;
38};
39
40class ScriptInterpreterIORedirect {
41public:
42 /// Create an IO redirect. If IO is enabled, this will redirects the output
43 /// to the command return object if set or to the debugger otherwise. If IO
44 /// is disabled, it will redirect all IO to /dev/null.
45 static llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
46 Create(bool enable_io, Debugger &debugger, CommandReturnObject *result);
47
48 ~ScriptInterpreterIORedirect();
49
50 lldb::FileSP GetInputFile() const { return m_input_file_sp; }
51 lldb::FileSP GetOutputFile() const { return m_output_file_sp->GetFileSP(); }
52 lldb::FileSP GetErrorFile() const { return m_error_file_sp->GetFileSP(); }
53
54 /// Flush our output and error file handles.
55 void Flush();
56
57private:
58 ScriptInterpreterIORedirect(std::unique_ptr<File> input,
59 std::unique_ptr<File> output);
60 ScriptInterpreterIORedirect(Debugger &debugger, CommandReturnObject *result);
61
62 lldb::FileSP m_input_file_sp;
63 lldb::StreamFileSP m_output_file_sp;
64 lldb::StreamFileSP m_error_file_sp;
65 Communication m_communication;
66 bool m_disconnect;
67};
68
69class ScriptInterpreter : public PluginInterface {
70public:
71 enum ScriptReturnType {
72 eScriptReturnTypeCharPtr,
73 eScriptReturnTypeBool,
74 eScriptReturnTypeShortInt,
75 eScriptReturnTypeShortIntUnsigned,
76 eScriptReturnTypeInt,
77 eScriptReturnTypeIntUnsigned,
78 eScriptReturnTypeLongInt,
79 eScriptReturnTypeLongIntUnsigned,
80 eScriptReturnTypeLongLong,
81 eScriptReturnTypeLongLongUnsigned,
82 eScriptReturnTypeFloat,
83 eScriptReturnTypeDouble,
84 eScriptReturnTypeChar,
85 eScriptReturnTypeCharStrOrNone,
86 eScriptReturnTypeOpaqueObject
87 };
88
89 ScriptInterpreter(
90 Debugger &debugger, lldb::ScriptLanguage script_lang,
91 lldb::ScriptedProcessInterfaceUP scripted_process_interface_up = {});
92
93 ~ScriptInterpreter() override = default;
94
95 struct ExecuteScriptOptions {
96 public:
97 ExecuteScriptOptions()
98 : m_enable_io(true), m_set_lldb_globals(true), m_maskout_errors(true) {}
99
100 bool GetEnableIO() const { return m_enable_io; }
101
102 bool GetSetLLDBGlobals() const { return m_set_lldb_globals; }
103
104 // If this is true then any exceptions raised by the script will be
105 // cleared with PyErr_Clear(). If false then they will be left for
106 // the caller to clean up
107 bool GetMaskoutErrors() const { return m_maskout_errors; }
108
109 ExecuteScriptOptions &SetEnableIO(bool enable) {
110 m_enable_io = enable;
111 return *this;
112 }
113
114 ExecuteScriptOptions &SetSetLLDBGlobals(bool set) {
115 m_set_lldb_globals = set;
116 return *this;
117 }
118
119 ExecuteScriptOptions &SetMaskoutErrors(bool maskout) {
120 m_maskout_errors = maskout;
121 return *this;
122 }
123
124 private:
125 bool m_enable_io;
126 bool m_set_lldb_globals;
127 bool m_maskout_errors;
128 };
129
130 virtual bool Interrupt() { return false; }
131
132 virtual bool ExecuteOneLine(
133 llvm::StringRef command, CommandReturnObject *result,
134 const ExecuteScriptOptions &options = ExecuteScriptOptions()) = 0;
135
136 virtual void ExecuteInterpreterLoop() = 0;
137
138 virtual bool ExecuteOneLineWithReturn(
139 llvm::StringRef in_string, ScriptReturnType return_type, void *ret_value,
140 const ExecuteScriptOptions &options = ExecuteScriptOptions()) {
141 return true;
142 }
143
144 virtual Status ExecuteMultipleLines(
145 const char *in_string,
146 const ExecuteScriptOptions &options = ExecuteScriptOptions()) {
147 Status error;
148 error.SetErrorString("not implemented");
149 return error;
150 }
151
152 virtual Status
153 ExportFunctionDefinitionToInterpreter(StringList &function_def) {
154 Status error;
155 error.SetErrorString("not implemented");
156 return error;
157 }
158
159 virtual Status GenerateBreakpointCommandCallbackData(
160 StringList &input,
161 std::string &output,
162 bool has_extra_args) {
163 Status error;
164 error.SetErrorString("not implemented");
165 return error;
166 }
167
168 virtual bool GenerateWatchpointCommandCallbackData(StringList &input,
169 std::string &output) {
170 return false;
171 }
172
173 virtual bool GenerateTypeScriptFunction(const char *oneliner,
174 std::string &output,
175 const void *name_token = nullptr) {
176 return false;
177 }
178
179 virtual bool GenerateTypeScriptFunction(StringList &input,
180 std::string &output,
181 const void *name_token = nullptr) {
182 return false;
183 }
184
185 virtual bool GenerateScriptAliasFunction(StringList &input,
186 std::string &output) {
187 return false;
188 }
189
190 virtual bool GenerateTypeSynthClass(StringList &input, std::string &output,
191 const void *name_token = nullptr) {
192 return false;
193 }
194
195 virtual bool GenerateTypeSynthClass(const char *oneliner, std::string &output,
196 const void *name_token = nullptr) {
197 return false;
198 }
199
200 virtual StructuredData::ObjectSP
201 CreateSyntheticScriptedProvider(const char *class_name,
202 lldb::ValueObjectSP valobj) {
203 return StructuredData::ObjectSP();
204 }
205
206 virtual StructuredData::GenericSP
207 CreateScriptCommandObject(const char *class_name) {
208 return StructuredData::GenericSP();
209 }
210
211 virtual StructuredData::GenericSP
212 CreateFrameRecognizer(const char *class_name) {
213 return StructuredData::GenericSP();
214 }
215
216 virtual lldb::ValueObjectListSP GetRecognizedArguments(
217 const StructuredData::ObjectSP &implementor,
218 lldb::StackFrameSP frame_sp) {
219 return lldb::ValueObjectListSP();
220 }
221
222 virtual StructuredData::GenericSP
223 OSPlugin_CreatePluginObject(const char *class_name,
224 lldb::ProcessSP process_sp) {
225 return StructuredData::GenericSP();
226 }
227
228 virtual StructuredData::DictionarySP
229 OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) {
230 return StructuredData::DictionarySP();
231 }
232
233 virtual StructuredData::ArraySP
234 OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) {
235 return StructuredData::ArraySP();
236 }
237
238 virtual StructuredData::StringSP
239 OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp,
240 lldb::tid_t thread_id) {
241 return StructuredData::StringSP();
242 }
243
244 virtual StructuredData::DictionarySP
245 OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp,
246 lldb::tid_t tid, lldb::addr_t context) {
247 return StructuredData::DictionarySP();
248 }
249
250 virtual StructuredData::ObjectSP
251 CreateScriptedThreadPlan(const char *class_name,
252 StructuredDataImpl *args_data,
253 std::string &error_str,
254 lldb::ThreadPlanSP thread_plan_sp) {
255 return StructuredData::ObjectSP();
256 }
257
258 virtual bool
259 ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp,
260 Event *event, bool &script_error) {
261 script_error = true;
262 return true;
263 }
264
265 virtual bool
266 ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp,
267 Event *event, bool &script_error) {
268 script_error = true;
269 return true;
270 }
271
272 virtual bool
273 ScriptedThreadPlanIsStale(StructuredData::ObjectSP implementor_sp,
274 bool &script_error) {
275 script_error = true;
276 return true;
277 }
278
279 virtual lldb::StateType
280 ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp,
281 bool &script_error) {
282 script_error = true;
283 return lldb::eStateStepping;
284 }
285
286 virtual StructuredData::GenericSP
287 CreateScriptedBreakpointResolver(const char *class_name,
288 StructuredDataImpl *args_data,
289 lldb::BreakpointSP &bkpt_sp) {
290 return StructuredData::GenericSP();
291 }
292
293 virtual bool
294 ScriptedBreakpointResolverSearchCallback(StructuredData::GenericSP implementor_sp,
295 SymbolContext *sym_ctx)
296 {
297 return false;
298 }
299
300 virtual lldb::SearchDepth
301 ScriptedBreakpointResolverSearchDepth(StructuredData::GenericSP implementor_sp)
302 {
303 return lldb::eSearchDepthModule;
304 }
305
306 virtual StructuredData::GenericSP
307 CreateScriptedStopHook(lldb::TargetSP target_sp, const char *class_name,
308 StructuredDataImpl *args_data, Status &error) {
309 error.SetErrorString("Creating scripted stop-hooks with the current "
310 "script interpreter is not supported.");
311 return StructuredData::GenericSP();
312 }
313
314 // This dispatches to the handle_stop method of the stop-hook class. It
315 // returns a "should_stop" bool.
316 virtual bool
317 ScriptedStopHookHandleStop(StructuredData::GenericSP implementor_sp,
318 ExecutionContext &exc_ctx,
319 lldb::StreamSP stream_sp) {
320 return true;
321 }
322
323 virtual StructuredData::ObjectSP
324 LoadPluginModule(const FileSpec &file_spec, lldb_private::Status &error) {
325 return StructuredData::ObjectSP();
326 }
327
328 virtual StructuredData::DictionarySP
329 GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target,
330 const char *setting_name, lldb_private::Status &error) {
331 return StructuredData::DictionarySP();
332 }
333
334 virtual Status GenerateFunction(const char *signature,
335 const StringList &input) {
336 Status error;
337 error.SetErrorString("unimplemented");
338 return error;
339 }
340
341 virtual void CollectDataForBreakpointCommandCallback(
342 std::vector<BreakpointOptions *> &options, CommandReturnObject &result);
343
344 virtual void
345 CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options,
346 CommandReturnObject &result);
347
348 /// Set the specified text as the callback for the breakpoint.
349 Status
350 SetBreakpointCommandCallback(std::vector<BreakpointOptions *> &bp_options_vec,
351 const char *callback_text);
352
353 virtual Status SetBreakpointCommandCallback(BreakpointOptions *bp_options,
354 const char *callback_text) {
355 Status error;
356 error.SetErrorString("unimplemented");
357 return error;
358 }
359
360 /// This one is for deserialization:
361 virtual Status SetBreakpointCommandCallback(
362 BreakpointOptions *bp_options,
363 std::unique_ptr<BreakpointOptions::CommandData> &data_up) {
364 Status error;
365 error.SetErrorString("unimplemented");
366 return error;
367 }
368
369 Status SetBreakpointCommandCallbackFunction(
370 std::vector<BreakpointOptions *> &bp_options_vec,
371 const char *function_name, StructuredData::ObjectSP extra_args_sp);
372
373 /// Set a script function as the callback for the breakpoint.
374 virtual Status
375 SetBreakpointCommandCallbackFunction(
376 BreakpointOptions *bp_options,
377 const char *function_name,
378 StructuredData::ObjectSP extra_args_sp) {
379 Status error;
380 error.SetErrorString("unimplemented");
381 return error;
382 }
383
384 /// Set a one-liner as the callback for the watchpoint.
385 virtual void SetWatchpointCommandCallback(WatchpointOptions *wp_options,
386 const char *oneliner) {}
387
388 virtual bool GetScriptedSummary(const char *function_name,
389 lldb::ValueObjectSP valobj,
390 StructuredData::ObjectSP &callee_wrapper_sp,
391 const TypeSummaryOptions &options,
392 std::string &retval) {
393 return false;
394 }
395
396 virtual void Clear() {
397 // Clean up any ref counts to SBObjects that might be in global variables
398 }
399
400 virtual size_t
401 CalculateNumChildren(const StructuredData::ObjectSP &implementor,
402 uint32_t max) {
403 return 0;
404 }
405
406 virtual lldb::ValueObjectSP
407 GetChildAtIndex(const StructuredData::ObjectSP &implementor, uint32_t idx) {
408 return lldb::ValueObjectSP();
409 }
410
411 virtual int
412 GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor,
413 const char *child_name) {
414 return UINT32_MAX;
415 }
416
417 virtual bool
418 UpdateSynthProviderInstance(const StructuredData::ObjectSP &implementor) {
419 return false;
420 }
421
422 virtual bool MightHaveChildrenSynthProviderInstance(
423 const StructuredData::ObjectSP &implementor) {
424 return true;
425 }
426
427 virtual lldb::ValueObjectSP
428 GetSyntheticValue(const StructuredData::ObjectSP &implementor) {
429 return nullptr;
430 }
431
432 virtual ConstString
433 GetSyntheticTypeName(const StructuredData::ObjectSP &implementor) {
434 return ConstString();
435 }
436
437 virtual bool
438 RunScriptBasedCommand(const char *impl_function, llvm::StringRef args,
439 ScriptedCommandSynchronicity synchronicity,
440 lldb_private::CommandReturnObject &cmd_retobj,
441 Status &error,
442 const lldb_private::ExecutionContext &exe_ctx) {
443 return false;
444 }
445
446 virtual bool RunScriptBasedCommand(
447 StructuredData::GenericSP impl_obj_sp, llvm::StringRef args,
448 ScriptedCommandSynchronicity synchronicity,
449 lldb_private::CommandReturnObject &cmd_retobj, Status &error,
450 const lldb_private::ExecutionContext &exe_ctx) {
451 return false;
452 }
453
454 virtual bool RunScriptFormatKeyword(const char *impl_function,
455 Process *process, std::string &output,
456 Status &error) {
457 error.SetErrorString("unimplemented");
458 return false;
459 }
460
461 virtual bool RunScriptFormatKeyword(const char *impl_function, Thread *thread,
462 std::string &output, Status &error) {
463 error.SetErrorString("unimplemented");
464 return false;
465 }
466
467 virtual bool RunScriptFormatKeyword(const char *impl_function, Target *target,
468 std::string &output, Status &error) {
469 error.SetErrorString("unimplemented");
470 return false;
471 }
472
473 virtual bool RunScriptFormatKeyword(const char *impl_function,
474 StackFrame *frame, std::string &output,
475 Status &error) {
476 error.SetErrorString("unimplemented");
477 return false;
478 }
479
480 virtual bool RunScriptFormatKeyword(const char *impl_function,
481 ValueObject *value, std::string &output,
482 Status &error) {
483 error.SetErrorString("unimplemented");
484 return false;
485 }
486
487 virtual bool GetDocumentationForItem(const char *item, std::string &dest) {
488 dest.clear();
489 return false;
490 }
491
492 virtual bool
493 GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp,
494 std::string &dest) {
495 dest.clear();
496 return false;
497 }
498
499 virtual uint32_t
500 GetFlagsForCommandObject(StructuredData::GenericSP cmd_obj_sp) {
501 return 0;
502 }
503
504 virtual bool GetLongHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp,
505 std::string &dest) {
506 dest.clear();
507 return false;
508 }
509
510 virtual bool CheckObjectExists(const char *name) { return false; }
511
512 virtual bool
513 LoadScriptingModule(const char *filename, bool init_session,
514 lldb_private::Status &error,
515 StructuredData::ObjectSP *module_sp = nullptr,
516 FileSpec extra_search_dir = {});
517
518 virtual bool IsReservedWord(const char *word) { return false; }
519
520 virtual std::unique_ptr<ScriptInterpreterLocker> AcquireInterpreterLock();
521
522 const char *GetScriptInterpreterPtyName();
523
524 virtual llvm::Expected<unsigned>
525 GetMaxPositionalArgumentsForCallable(const llvm::StringRef &callable_name) {
526 return llvm::createStringError(
527 llvm::inconvertibleErrorCode(), "Unimplemented function");
528 }
529
530 static std::string LanguageToString(lldb::ScriptLanguage language);
531
532 static lldb::ScriptLanguage StringToLanguage(const llvm::StringRef &string);
533
534 lldb::ScriptLanguage GetLanguage() { return m_script_lang; }
535
536 ScriptedProcessInterface &GetScriptedProcessInterface() {
537 return *m_scripted_process_interface_up;
538 }
539
540 lldb::DataExtractorSP
541 GetDataExtractorFromSBData(const lldb::SBData &data) const;
542
543 Status GetStatusFromSBError(const lldb::SBError &error) const;
544
545protected:
546 Debugger &m_debugger;
547 lldb::ScriptLanguage m_script_lang;
548 lldb::ScriptedProcessInterfaceUP m_scripted_process_interface_up;
549};
550
551} // namespace lldb_private
552
553#endif // LLDB_INTERPRETER_SCRIPTINTERPRETER_H
554