[Go to site: main page, start]

LLDB mainline
ScriptInterpreter.cpp
Go to the documentation of this file.
1//===-- ScriptInterpreter.cpp ---------------------------------------------===//
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
10#include "lldb/Core/Debugger.h"
12#include "lldb/Host/Pipe.h"
15#include "lldb/Utility/Status.h"
16#include "lldb/Utility/Stream.h"
19#include "llvm/ADT/StringSwitch.h"
20#if defined(_WIN32)
22#endif
23#include <cstdio>
24#include <cstdlib>
25#include <memory>
26#include <optional>
27#include <string>
28
29using namespace lldb;
30using namespace lldb_private;
31
33 lldb::ScriptLanguage script_lang)
34 : m_debugger(debugger), m_script_lang(script_lang) {}
35
37 std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
38 CommandReturnObject &result) {
39 result.AppendError(
40 "This script interpreter does not support breakpoint callbacks.");
41}
42
44 WatchpointOptions *bp_options, CommandReturnObject &result) {
45 result.AppendError(
46 "This script interpreter does not support watchpoint callbacks.");
47}
48
52
54 const std::string &name, std::vector<ExtensionTemplateRequest> &extensions,
55 bool generate_non_abstract_methods, std::string output_file) {
56 return llvm::make_error<UnimplementedError>();
57}
58
60 const char *filename, const LoadScriptOptions &options,
62 FileSpec extra_search_dir, lldb::TargetSP loaded_into_target_sp) {
64 "This script interpreter does not support importing modules.");
65 return false;
66}
67
69 switch (language) {
71 return "None";
73 return "Python";
75 return "Lua";
77 return "Unknown";
78 }
79 llvm_unreachable("Unhandled ScriptInterpreter!");
80}
81
83ScriptInterpreter::StringToLanguage(const llvm::StringRef &language) {
84 if (language.equals_insensitive(LanguageToString(eScriptLanguageNone)))
86 if (language.equals_insensitive(LanguageToString(eScriptLanguagePython)))
88 if (language.equals_insensitive(LanguageToString(eScriptLanguageLua)))
89 return eScriptLanguageLua;
91}
92
93llvm::StringLiteral
95 switch (extension) {
97 return "Invalid";
99 return "OperatingSystem";
101 return "ScriptedPlatform";
103 return "ScriptedProcess";
105 return "ScriptedBreakpointResolver";
107 return "ScriptedThreadPlan";
109 return "ScriptedFrameProvider";
111 return "ScriptedHook";
113 return "ScriptedThread";
115 return "ScriptedFrame";
117 return "ScriptedStackFrameRecognizer";
119 return "ScriptedCommand";
121 return "ParsedCommand";
123 return "ScriptedStringSummary";
125 return "ScriptedSyntheticChildren";
126 }
127 llvm_unreachable("unhandled ScriptedExtension");
128}
129
132 return llvm::StringSwitch<lldb::ScriptedExtension>(string)
133 .CaseLower("OperatingSystem", eScriptedExtensionOperatingSystem)
134 .CaseLower("ScriptedPlatform", eScriptedExtensionScriptedPlatform)
135 .CaseLower("ScriptedProcess", eScriptedExtensionScriptedProcess)
136 .CaseLower("ScriptedBreakpointResolver",
138 .CaseLower("ScriptedThreadPlan", eScriptedExtensionScriptedThreadPlan)
139 .CaseLower("ScriptedFrameProvider",
141 .CaseLower("ScriptedHook", eScriptedExtensionScriptedHook)
142 .CaseLower("ScriptedThread", eScriptedExtensionScriptedThread)
143 .CaseLower("ScriptedFrame", eScriptedExtensionScriptedFrame)
144 .CaseLower("ScriptedStackFrameRecognizer",
146 .CaseLower("ScriptedCommand", eScriptedExtensionScriptedCommand)
147 .CaseLower("ParsedCommand", eScriptedExtensionParsedCommand)
148 .CaseLower("ScriptedStringSummary",
150 .CaseLower("ScriptedSyntheticChildren",
153}
154
156 std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
157 const char *callback_text) {
159 for (BreakpointOptions &bp_options : bp_options_vec) {
160 error = SetBreakpointCommandCallback(bp_options, callback_text,
161 /*is_callback=*/false);
162 if (!error.Success())
163 break;
164 }
165 return error;
166}
167
169 std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
170 const char *function_name, StructuredData::ObjectSP extra_args_sp) {
172 for (BreakpointOptions &bp_options : bp_options_vec) {
173 error = SetBreakpointCommandCallbackFunction(bp_options, function_name,
174 extra_args_sp);
175 if (!error.Success())
176 return error;
177 }
178 return error;
179}
180
181std::unique_ptr<ScriptInterpreterLocker>
183 return std::make_unique<ScriptInterpreterLocker>();
184}
185
188 std::string sanitized_name(name);
189 std::string conflicting_keyword;
190
191 // FIXME: for Python, don't allow certain characters in imported module
192 // filenames. Theoretically, different scripting languages may have
193 // different sets of forbidden tokens in filenames, and that should
194 // be dealt with by each ScriptInterpreter. For now, just replace dots
195 // with underscores. In order to support anything other than Python
196 // this will need to be reworked.
197 llvm::replace(sanitized_name, '.', '_');
198 llvm::replace(sanitized_name, ' ', '_');
199 llvm::replace(sanitized_name, '-', '_');
200 llvm::replace(sanitized_name, '+', 'x');
201
202 if (IsReservedWord(sanitized_name.c_str())) {
203 conflicting_keyword = sanitized_name;
204 sanitized_name.insert(sanitized_name.begin(), '_');
205 }
206
208 name.str(), std::move(sanitized_name), std::move(conflicting_keyword));
209}
210
211static void ReadThreadBytesReceived(void *baton, const void *src,
212 size_t src_len) {
213 if (src && src_len) {
214 Stream *strm = (Stream *)baton;
215 strm->Write(src, src_len);
216 strm->Flush();
217 }
218}
219
220llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
222 CommandReturnObject *result) {
223 if (enable_io)
224 return std::unique_ptr<ScriptInterpreterIORedirect>(
225 new ScriptInterpreterIORedirect(debugger, result));
226
229 if (!nullin)
230 return nullin.takeError();
231
234 if (!nullout)
235 return nullout.takeError();
236
237 return std::unique_ptr<ScriptInterpreterIORedirect>(
238 new ScriptInterpreterIORedirect(std::move(*nullin), std::move(*nullout)));
239}
240
242 std::unique_ptr<File> input, std::unique_ptr<File> output)
243 : m_input_file_sp(std::move(input)),
244 m_output_file_sp(std::make_shared<LockableStreamFile>(std::move(output),
247 m_communication("lldb.ScriptInterpreterIORedirect.comm"),
248 m_disconnect(false) {}
249
251 Debugger &debugger, CommandReturnObject *result)
252 : m_communication("lldb.ScriptInterpreterIORedirect.comm"),
253 m_disconnect(false) {
254
255 if (result) {
256 m_input_file_sp = debugger.GetInputFileSP();
257
258 Pipe pipe;
259 Status pipe_result = pipe.CreateNew();
260#if defined(_WIN32)
261 lldb::file_t read_file = pipe.GetReadNativeHandle();
263 std::unique_ptr<ConnectionGenericFile> conn_up =
264 std::make_unique<ConnectionGenericFile>(read_file, true);
265#else
266 std::unique_ptr<ConnectionFileDescriptor> conn_up =
267 std::make_unique<ConnectionFileDescriptor>(
268 pipe.ReleaseReadFileDescriptor(), true);
269#endif
270
271 if (conn_up->IsConnected()) {
272 m_communication.SetConnection(std::move(conn_up));
273 m_communication.SetReadThreadBytesReceivedCallback(
275 m_communication.StartReadThread();
276 m_disconnect = true;
277
278 FILE *outfile_handle = fdopen(pipe.ReleaseWriteFileDescriptor(), "w");
279 m_output_file_sp = std::make_shared<LockableStreamFile>(
280 std::make_shared<StreamFile>(outfile_handle, NativeFile::Owned),
283 if (outfile_handle)
284 ::setbuf(outfile_handle, nullptr);
285
286 result->SetImmediateOutputFile(debugger.GetOutputFileSP());
287 result->SetImmediateErrorFile(debugger.GetErrorFileSP());
288 }
289 }
290
294}
295
298 m_output_file_sp->Lock().Flush();
299 if (m_error_file_sp)
300 m_error_file_sp->Lock().Flush();
301}
302
304 if (!m_disconnect)
305 return;
306
307 assert(m_output_file_sp);
308 assert(m_error_file_sp);
310
311 // Close the write end of the pipe since we are done with our one line
312 // script. This should cause the read thread that output_comm is using to
313 // exit.
314 m_output_file_sp->GetUnlockedFile().Close();
315 // The close above should cause this thread to exit when it gets to the end
316 // of file, so let it get all its data.
317 m_communication.JoinReadThread();
318 // Now we can close the read end of the pipe.
319 m_communication.Disconnect();
320}
static llvm::raw_ostream & error(Stream &strm)
static void ReadThreadBytesReceived(void *baton, const void *src, size_t src_len)
"lldb/Breakpoint/BreakpointOptions.h" Class that manages the options on a breakpoint or breakpoint lo...
void SetImmediateErrorFile(lldb::FileSP file_sp)
void AppendError(llvm::StringRef in_string)
void SetImmediateOutputFile(lldb::FileSP file_sp)
A class to manage flag bits.
Definition Debugger.h:100
lldb::FileSP GetInputFileSP()
Definition Debugger.h:155
lldb::FileSP GetErrorFileSP()
Definition Debugger.h:162
lldb::FileSP GetOutputFileSP()
Definition Debugger.h:158
void AdoptTopIOHandlerFilesIfInvalid(lldb::FileSP &in, lldb::LockableStreamFileSP &out, lldb::LockableStreamFileSP &err)
A file utility class.
Definition FileSpec.h:56
static const char * DEV_NULL
Definition FileSystem.h:32
int Open(const char *path, int flags, int mode=0600)
Wraps open in a platform-independent way.
static FileSystem & Instance()
Status CreateNew() override
Definition PipePosix.cpp:82
int ReleaseReadFileDescriptor() override
int ReleaseWriteFileDescriptor() override
void Flush()
Flush our output and error file handles.
ScriptInterpreterIORedirect(std::unique_ptr< File > input, std::unique_ptr< File > output)
static llvm::Expected< std::unique_ptr< ScriptInterpreterIORedirect > > Create(bool enable_io, Debugger &debugger, CommandReturnObject *result)
Create an IO redirect.
Holds an lldb_private::Module name and a "sanitized" version of it for the purposes of loading a scri...
static lldb::ScriptLanguage StringToLanguage(const llvm::StringRef &string)
virtual void CollectDataForBreakpointCommandCallback(std::vector< std::reference_wrapper< BreakpointOptions > > &options, CommandReturnObject &result)
virtual llvm::Expected< FileSpec > GenerateExtensionTemplate(const std::string &name, std::vector< ExtensionTemplateRequest > &extensions, bool generate_non_abstract_methods, std::string output_file)
static llvm::StringLiteral ExtensionToString(lldb::ScriptedExtension extension)
static lldb::ScriptedExtension StringToExtension(llvm::StringRef string)
Status SetBreakpointCommandCallback(std::vector< std::reference_wrapper< BreakpointOptions > > &bp_options_vec, const char *callback_text)
Set the specified text as the callback for the breakpoint.
virtual bool LoadScriptingModule(const char *filename, const LoadScriptOptions &options, lldb_private::Status &error, StructuredData::ObjectSP *module_sp=nullptr, FileSpec extra_search_dir={}, lldb::TargetSP loaded_into_target_sp={})
static std::string LanguageToString(lldb::ScriptLanguage language)
virtual std::unique_ptr< ScriptInterpreterLocker > AcquireInterpreterLock()
virtual StructuredData::DictionarySP GetInterpreterInfo()
Status SetBreakpointCommandCallbackFunction(std::vector< std::reference_wrapper< BreakpointOptions > > &bp_options_vec, const char *function_name, StructuredData::ObjectSP extra_args_sp)
virtual bool IsReservedWord(const char *word)
ScriptInterpreter(Debugger &debugger, lldb::ScriptLanguage script_lang)
virtual void CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options, CommandReturnObject &result)
virtual SanitizedScriptingModuleName GetSanitizedScriptingModuleName(llvm::StringRef name)
An error handling class.
Definition Status.h:118
static Status FromErrorString(const char *str)
Definition Status.h:141
A stream class that can stream formatted output to a file.
Definition Stream.h:28
size_t Write(const void *src, size_t src_len)
Output character bytes to the stream.
Definition Stream.h:111
virtual void Flush()=0
Flush the stream.
std::shared_ptr< Dictionary > DictionarySP
std::shared_ptr< Object > ObjectSP
"lldb/Breakpoint/WatchpointOptions.h" Class that manages the options on a watchpoint.
A class that represents a running process on the host machine.
PipePosix Pipe
Definition Pipe.h:20
int file_t
Definition lldb-types.h:59
ScriptLanguage
Script interpreter types.
@ eScriptLanguageUnknown
@ eScriptLanguageNone
@ eScriptLanguagePython
ScriptedExtension
Scripting extension types.
@ eScriptedExtensionOperatingSystem
@ eScriptedExtensionScriptedHook
@ eScriptedExtensionParsedCommand
@ eScriptedExtensionScriptedPlatform
@ eScriptedExtensionScriptedCommand
@ eScriptedExtensionScriptedProcess
@ eScriptedExtensionScriptedFrame
@ eScriptedExtensionScriptedBreakpointResolver
@ eScriptedExtensionScriptedThreadPlan
@ eScriptedExtensionScriptedStringSummary
@ eScriptedExtensionScriptedFrameProvider
@ eScriptedExtensionScriptedThread
@ eScriptedExtensionScriptedStackFrameRecognizer
@ eScriptedExtensionScriptedSyntheticChildren
@ eScriptedExtensionInvalid
std::shared_ptr< lldb_private::Target > TargetSP