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"
18#if defined(_WIN32)
20#endif
21#include <cstdio>
22#include <cstdlib>
23#include <memory>
24#include <optional>
25#include <string>
26
27using namespace lldb;
28using namespace lldb_private;
29
31 Debugger &debugger, lldb::ScriptLanguage script_lang,
32 lldb::ScriptedPlatformInterfaceUP scripted_platform_interface_up)
33 : m_debugger(debugger), m_script_lang(script_lang),
34 m_scripted_platform_interface_up(
35 std::move(scripted_platform_interface_up)) {}
36
38 std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
39 CommandReturnObject &result) {
40 result.AppendError(
41 "This script interpreter does not support breakpoint callbacks.");
42}
43
45 WatchpointOptions *bp_options, CommandReturnObject &result) {
46 result.AppendError(
47 "This script interpreter does not support watchpoint callbacks.");
48}
49
51 return nullptr;
52}
53
55 const LoadScriptOptions &options,
57 StructuredData::ObjectSP *module_sp,
58 FileSpec extra_search_dir) {
59 error.SetErrorString(
60 "This script interpreter does not support importing modules.");
61 return false;
62}
63
65 switch (language) {
67 return "None";
69 return "Python";
71 return "Lua";
73 return "Unknown";
74 }
75 llvm_unreachable("Unhandled ScriptInterpreter!");
76}
77
80 return data.m_opaque_sp;
81}
82
84 const lldb::SBBreakpoint &breakpoint) const {
85 return breakpoint.m_opaque_wp.lock();
86}
87
89 const lldb::SBAttachInfo &attach_info) const {
90 return attach_info.m_opaque_sp;
91}
92
94 const lldb::SBLaunchInfo &launch_info) const {
95 return std::make_shared<ProcessLaunchInfo>(
96 *reinterpret_cast<ProcessLaunchInfo *>(launch_info.m_opaque_sp.get()));
97}
98
101 if (error.m_opaque_up)
102 return *error.m_opaque_up;
103
104 return Status();
105}
106
107std::optional<MemoryRegionInfo>
109 const lldb::SBMemoryRegionInfo &mem_region) const {
110 if (!mem_region.m_opaque_up)
111 return std::nullopt;
112 return *mem_region.m_opaque_up.get();
113}
114
116ScriptInterpreter::StringToLanguage(const llvm::StringRef &language) {
117 if (language.equals_insensitive(LanguageToString(eScriptLanguageNone)))
118 return eScriptLanguageNone;
119 if (language.equals_insensitive(LanguageToString(eScriptLanguagePython)))
121 if (language.equals_insensitive(LanguageToString(eScriptLanguageLua)))
122 return eScriptLanguageLua;
124}
125
127 std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
128 const char *callback_text) {
130 for (BreakpointOptions &bp_options : bp_options_vec) {
131 error = SetBreakpointCommandCallback(bp_options, callback_text,
132 /*is_callback=*/false);
133 if (!error.Success())
134 break;
135 }
136 return error;
137}
138
140 std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
141 const char *function_name, StructuredData::ObjectSP extra_args_sp) {
143 for (BreakpointOptions &bp_options : bp_options_vec) {
144 error = SetBreakpointCommandCallbackFunction(bp_options, function_name,
145 extra_args_sp);
146 if (!error.Success())
147 return error;
148 }
149 return error;
150}
151
152std::unique_ptr<ScriptInterpreterLocker>
154 return std::make_unique<ScriptInterpreterLocker>();
155}
156
157static void ReadThreadBytesReceived(void *baton, const void *src,
158 size_t src_len) {
159 if (src && src_len) {
160 Stream *strm = (Stream *)baton;
161 strm->Write(src, src_len);
162 strm->Flush();
163 }
164}
165
166llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
168 CommandReturnObject *result) {
169 if (enable_io)
170 return std::unique_ptr<ScriptInterpreterIORedirect>(
171 new ScriptInterpreterIORedirect(debugger, result));
172
175 if (!nullin)
176 return nullin.takeError();
177
180 if (!nullout)
181 return nullin.takeError();
182
183 return std::unique_ptr<ScriptInterpreterIORedirect>(
184 new ScriptInterpreterIORedirect(std::move(*nullin), std::move(*nullout)));
185}
186
188 std::unique_ptr<File> input, std::unique_ptr<File> output)
189 : m_input_file_sp(std::move(input)),
190 m_output_file_sp(std::make_shared<StreamFile>(std::move(output))),
191 m_error_file_sp(m_output_file_sp),
192 m_communication("lldb.ScriptInterpreterIORedirect.comm"),
193 m_disconnect(false) {}
194
196 Debugger &debugger, CommandReturnObject *result)
197 : m_communication("lldb.ScriptInterpreterIORedirect.comm"),
198 m_disconnect(false) {
199
200 if (result) {
201 m_input_file_sp = debugger.GetInputFileSP();
202
203 Pipe pipe;
204 Status pipe_result = pipe.CreateNew(false);
205#if defined(_WIN32)
206 lldb::file_t read_file = pipe.GetReadNativeHandle();
208 std::unique_ptr<ConnectionGenericFile> conn_up =
209 std::make_unique<ConnectionGenericFile>(read_file, true);
210#else
211 std::unique_ptr<ConnectionFileDescriptor> conn_up =
212 std::make_unique<ConnectionFileDescriptor>(
213 pipe.ReleaseReadFileDescriptor(), true);
214#endif
215
216 if (conn_up->IsConnected()) {
217 m_communication.SetConnection(std::move(conn_up));
221 m_disconnect = true;
222
223 FILE *outfile_handle = fdopen(pipe.ReleaseWriteFileDescriptor(), "w");
224 m_output_file_sp = std::make_shared<StreamFile>(outfile_handle, true);
226 if (outfile_handle)
227 ::setbuf(outfile_handle, nullptr);
228
230 result->SetImmediateErrorFile(debugger.GetErrorStream().GetFileSP());
231 }
232 }
233
237}
238
241 m_output_file_sp->Flush();
242 if (m_error_file_sp)
243 m_error_file_sp->Flush();
244}
245
247 if (!m_disconnect)
248 return;
249
250 assert(m_output_file_sp);
251 assert(m_error_file_sp);
253
254 // Close the write end of the pipe since we are done with our one line
255 // script. This should cause the read thread that output_comm is using to
256 // exit.
257 m_output_file_sp->GetFile().Close();
258 // The close above should cause this thread to exit when it gets to the end
259 // of file, so let it get all its data.
261 // Now we can close the read end of the pipe.
263}
static llvm::raw_ostream & error(Stream &strm)
static void ReadThreadBytesReceived(void *baton, const void *src, size_t src_len)
ProcessAttachInfoSP m_opaque_sp
Definition: SBAttachInfo.h:205
lldb::BreakpointWP m_opaque_wp
Definition: SBBreakpoint.h:168
lldb::DataExtractorSP m_opaque_sp
Definition: SBData.h:159
std::shared_ptr< lldb_private::SBLaunchInfoImpl > m_opaque_sp
Definition: SBLaunchInfo.h:218
lldb::MemoryRegionInfoUP m_opaque_up
"lldb/Breakpoint/BreakpointOptions.h" Class that manages the options on a breakpoint or breakpoint lo...
void SetImmediateErrorFile(lldb::FileSP file_sp)
void void AppendError(llvm::StringRef in_string)
void SetImmediateOutputFile(lldb::FileSP file_sp)
A class to manage flag bits.
Definition: Debugger.h:79
StreamFile & GetOutputStream()
Definition: Debugger.h:153
lldb::FileSP GetInputFileSP()
Definition: Debugger.h:141
StreamFile & GetErrorStream()
Definition: Debugger.h:155
void AdoptTopIOHandlerFilesIfInvalid(lldb::FileSP &in, lldb::StreamFileSP &out, lldb::StreamFileSP &err)
Definition: Debugger.cpp:1168
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()
@ eOpenOptionReadOnly
Definition: File.h:51
@ eOpenOptionWriteOnly
Definition: File.h:52
A posix-based implementation of Pipe, a class that abtracts unix style pipes.
Definition: PipePosix.h:21
int ReleaseReadFileDescriptor() override
Definition: PipePosix.cpp:226
int ReleaseWriteFileDescriptor() override
Definition: PipePosix.cpp:237
Status CreateNew(bool child_process_inherit) override
Definition: PipePosix.cpp:80
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.
static lldb::ScriptLanguage StringToLanguage(const llvm::StringRef &string)
virtual void CollectDataForBreakpointCommandCallback(std::vector< std::reference_wrapper< BreakpointOptions > > &options, CommandReturnObject &result)
lldb::ProcessAttachInfoSP GetOpaqueTypeFromSBAttachInfo(const lldb::SBAttachInfo &attach_info) const
virtual bool LoadScriptingModule(const char *filename, const LoadScriptOptions &options, lldb_private::Status &error, StructuredData::ObjectSP *module_sp=nullptr, FileSpec extra_search_dir={})
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.
lldb::ProcessLaunchInfoSP GetOpaqueTypeFromSBLaunchInfo(const lldb::SBLaunchInfo &launch_info) const
static std::string LanguageToString(lldb::ScriptLanguage language)
Status GetStatusFromSBError(const lldb::SBError &error) const
std::optional< MemoryRegionInfo > GetOpaqueTypeFromSBMemoryRegionInfo(const lldb::SBMemoryRegionInfo &mem_region) const
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)
lldb::BreakpointSP GetOpaqueTypeFromSBBreakpoint(const lldb::SBBreakpoint &breakpoint) const
lldb::DataExtractorSP GetDataExtractorFromSBData(const lldb::SBData &data) const
virtual void CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options, CommandReturnObject &result)
ScriptInterpreter(Debugger &debugger, lldb::ScriptLanguage script_lang, lldb::ScriptedPlatformInterfaceUP scripted_platform_interface_up=std::make_unique< ScriptedPlatformInterface >())
An error handling class.
Definition: Status.h:44
std::shared_ptr< File > GetFileSP()
Definition: StreamFile.h:41
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:101
virtual void Flush()=0
Flush the stream.
std::shared_ptr< Dictionary > DictionarySP
std::shared_ptr< Object > ObjectSP
void SetConnection(std::unique_ptr< Connection > connection) override
Sets the connection that it to be used by this class.
lldb::ConnectionStatus Disconnect(Status *error_ptr=nullptr) override
Disconnect the communications connection if one is currently connected.
virtual bool StartReadThread(Status *error_ptr=nullptr)
Starts a read thread whose sole purpose it to read bytes from the current connection.
virtual bool JoinReadThread(Status *error_ptr=nullptr)
void SetReadThreadBytesReceivedCallback(ReadThreadBytesReceived callback, void *callback_baton)
"lldb/Breakpoint/WatchpointOptions.h" Class that manages the options on a watchpoint.
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
Definition: SBAddress.h:15
int file_t
Definition: lldb-types.h:59
std::unique_ptr< lldb_private::ScriptedPlatformInterface > ScriptedPlatformInterfaceUP
Definition: lldb-forward.h:388
ScriptLanguage
Script interpreter types.
@ eScriptLanguageUnknown
@ eScriptLanguageLua
@ eScriptLanguageNone
@ eScriptLanguagePython
std::shared_ptr< lldb_private::ProcessAttachInfo > ProcessAttachInfoSP
Definition: lldb-forward.h:369
std::shared_ptr< lldb_private::Breakpoint > BreakpointSP
Definition: lldb-forward.h:303
std::shared_ptr< lldb_private::DataExtractor > DataExtractorSP
Definition: lldb-forward.h:320
std::shared_ptr< lldb_private::ProcessLaunchInfo > ProcessLaunchInfoSP
Definition: lldb-forward.h:370