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 <string>
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 
29 ScriptInterpreter::ScriptInterpreter(
30  Debugger &debugger, lldb::ScriptLanguage script_lang,
31  lldb::ScriptedProcessInterfaceUP scripted_process_interface_up)
32  : m_debugger(debugger), m_script_lang(script_lang),
33  m_scripted_process_interface_up(
34  std::move(scripted_process_interface_up)) {}
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 
50  return nullptr;
51 }
52 
53 bool ScriptInterpreter::LoadScriptingModule(const char *filename,
54  const LoadScriptOptions &options,
56  StructuredData::ObjectSP *module_sp,
57  FileSpec extra_search_dir) {
58  error.SetErrorString(
59  "This script interpreter does not support importing modules.");
60  return false;
61 }
62 
64  switch (language) {
66  return "None";
68  return "Python";
69  case eScriptLanguageLua:
70  return "Lua";
72  return "Unknown";
73  }
74  llvm_unreachable("Unhandled ScriptInterpreter!");
75 }
76 
77 lldb::DataExtractorSP
79  return data.m_opaque_sp;
80 }
81 
82 Status
84  if (error.m_opaque_up)
85  return *error.m_opaque_up.get();
86 
87  return Status();
88 }
89 
90 llvm::Optional<MemoryRegionInfo>
92  const lldb::SBMemoryRegionInfo &mem_region) const {
93  if (!mem_region.m_opaque_up)
94  return llvm::None;
95  return *mem_region.m_opaque_up.get();
96 }
97 
99 ScriptInterpreter::StringToLanguage(const llvm::StringRef &language) {
100  if (language.equals_insensitive(LanguageToString(eScriptLanguageNone)))
101  return eScriptLanguageNone;
102  if (language.equals_insensitive(LanguageToString(eScriptLanguagePython)))
103  return eScriptLanguagePython;
104  if (language.equals_insensitive(LanguageToString(eScriptLanguageLua)))
105  return eScriptLanguageLua;
106  return eScriptLanguageUnknown;
107 }
108 
110  std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
111  const char *callback_text) {
112  Status error;
113  for (BreakpointOptions &bp_options : bp_options_vec) {
114  error = SetBreakpointCommandCallback(bp_options, callback_text);
115  if (!error.Success())
116  break;
117  }
118  return error;
119 }
120 
122  std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
123  const char *function_name, StructuredData::ObjectSP extra_args_sp) {
124  Status error;
125  for (BreakpointOptions &bp_options : bp_options_vec) {
126  error = SetBreakpointCommandCallbackFunction(bp_options, function_name,
127  extra_args_sp);
128  if (!error.Success())
129  return error;
130  }
131  return error;
132 }
133 
134 std::unique_ptr<ScriptInterpreterLocker>
136  return std::make_unique<ScriptInterpreterLocker>();
137 }
138 
139 static void ReadThreadBytesReceived(void *baton, const void *src,
140  size_t src_len) {
141  if (src && src_len) {
142  Stream *strm = (Stream *)baton;
143  strm->Write(src, src_len);
144  strm->Flush();
145  }
146 }
147 
148 llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
150  CommandReturnObject *result) {
151  if (enable_io)
152  return std::unique_ptr<ScriptInterpreterIORedirect>(
153  new ScriptInterpreterIORedirect(debugger, result));
154 
157  if (!nullin)
158  return nullin.takeError();
159 
162  if (!nullout)
163  return nullin.takeError();
164 
165  return std::unique_ptr<ScriptInterpreterIORedirect>(
166  new ScriptInterpreterIORedirect(std::move(*nullin), std::move(*nullout)));
167 }
168 
170  std::unique_ptr<File> input, std::unique_ptr<File> output)
171  : m_input_file_sp(std::move(input)),
172  m_output_file_sp(std::make_shared<StreamFile>(std::move(output))),
173  m_error_file_sp(m_output_file_sp),
174  m_communication("lldb.ScriptInterpreterIORedirect.comm"),
175  m_disconnect(false) {}
176 
178  Debugger &debugger, CommandReturnObject *result)
179  : m_communication("lldb.ScriptInterpreterIORedirect.comm"),
180  m_disconnect(false) {
181 
182  if (result) {
183  m_input_file_sp = debugger.GetInputFileSP();
184 
185  Pipe pipe;
186  Status pipe_result = pipe.CreateNew(false);
187 #if defined(_WIN32)
188  lldb::file_t read_file = pipe.GetReadNativeHandle();
189  pipe.ReleaseReadFileDescriptor();
190  std::unique_ptr<ConnectionGenericFile> conn_up =
191  std::make_unique<ConnectionGenericFile>(read_file, true);
192 #else
193  std::unique_ptr<ConnectionFileDescriptor> conn_up =
194  std::make_unique<ConnectionFileDescriptor>(
195  pipe.ReleaseReadFileDescriptor(), true);
196 #endif
197 
198  if (conn_up->IsConnected()) {
199  m_communication.SetConnection(std::move(conn_up));
203  m_disconnect = true;
204 
205  FILE *outfile_handle = fdopen(pipe.ReleaseWriteFileDescriptor(), "w");
206  m_output_file_sp = std::make_shared<StreamFile>(outfile_handle, true);
208  if (outfile_handle)
209  ::setbuf(outfile_handle, nullptr);
210 
211  result->SetImmediateOutputFile(debugger.GetOutputStream().GetFileSP());
212  result->SetImmediateErrorFile(debugger.GetErrorStream().GetFileSP());
213  }
214  }
215 
219 }
220 
222  if (m_output_file_sp)
223  m_output_file_sp->Flush();
224  if (m_error_file_sp)
225  m_error_file_sp->Flush();
226 }
227 
229  if (!m_disconnect)
230  return;
231 
232  assert(m_output_file_sp);
233  assert(m_error_file_sp);
235 
236  // Close the write end of the pipe since we are done with our one line
237  // script. This should cause the read thread that output_comm is using to
238  // exit.
239  m_output_file_sp->GetFile().Close();
240  // The close above should cause this thread to exit when it gets to the end
241  // of file, so let it get all its data.
243  // Now we can close the read end of the pipe.
245 }
lldb_private::ScriptInterpreter::SetBreakpointCommandCallback
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.
Definition: ScriptInterpreter.cpp:109
lldb_private::FileSystem::Open
int Open(const char *path, int flags, int mode)
Wraps ::open in a platform-independent way.
Definition: FileSystemPosix.cpp:79
lldb::ScriptLanguage
ScriptLanguage
Script interpreter types.
Definition: lldb-enumerations.h:217
lldb_private::Pipe
PipePosix Pipe
Definition: Pipe.h:20
lldb_private::Debugger::AdoptTopIOHandlerFilesIfInvalid
void AdoptTopIOHandlerFilesIfInvalid(lldb::FileSP &in, lldb::StreamFileSP &out, lldb::StreamFileSP &err)
Definition: Debugger.cpp:1098
lldb_private::ThreadedCommunication::SetConnection
void SetConnection(std::unique_ptr< Connection > connection) override
Sets the connection that it to be used by this class.
Definition: ThreadedCommunication.cpp:368
lldb::SBError
Definition: SBError.h:20
lldb_private::StreamFile::GetFileSP
std::shared_ptr< File > GetFileSP()
Definition: StreamFile.h:41
lldb_private::ScriptInterpreterIORedirect::m_error_file_sp
lldb::StreamFileSP m_error_file_sp
Definition: ScriptInterpreter.h:121
ConnectionGenericFileWindows.h
lldb_private::ScriptInterpreter::LoadScriptingModule
virtual bool LoadScriptingModule(const char *filename, const LoadScriptOptions &options, lldb_private::Status &error, StructuredData::ObjectSP *module_sp=nullptr, FileSpec extra_search_dir={})
Definition: ScriptInterpreter.cpp:53
lldb_private::ScriptInterpreter::GetStatusFromSBError
Status GetStatusFromSBError(const lldb::SBError &error) const
Definition: ScriptInterpreter.cpp:83
ReadThreadBytesReceived
static void ReadThreadBytesReceived(void *baton, const void *src, size_t src_len)
Definition: ScriptInterpreter.cpp:139
lldb_private::ScriptInterpreter::StringToLanguage
static lldb::ScriptLanguage StringToLanguage(const llvm::StringRef &string)
Definition: ScriptInterpreter.cpp:99
lldb_private::Stream::Flush
virtual void Flush()=0
Flush the stream.
lldb_private::Debugger::GetOutputStream
StreamFile & GetOutputStream()
Definition: Debugger.h:147
lldb_private::ScriptInterpreter::SetBreakpointCommandCallbackFunction
Status SetBreakpointCommandCallbackFunction(std::vector< std::reference_wrapper< BreakpointOptions >> &bp_options_vec, const char *function_name, StructuredData::ObjectSP extra_args_sp)
Definition: ScriptInterpreter.cpp:121
lldb_private::ThreadedCommunication::JoinReadThread
virtual bool JoinReadThread(Status *error_ptr=nullptr)
Definition: ThreadedCommunication.cpp:209
lldb_private::Stream
Definition: Stream.h:28
lldb::file_t
int file_t
Definition: lldb-types.h:59
lldb_private::ScriptInterpreterIORedirect::Create
static llvm::Expected< std::unique_ptr< ScriptInterpreterIORedirect > > Create(bool enable_io, Debugger &debugger, CommandReturnObject *result)
Create an IO redirect.
Definition: ScriptInterpreter.cpp:149
CommandReturnObject.h
lldb_private::FileSystem::DEV_NULL
static const char * DEV_NULL
Definition: FileSystem.h:30
Debugger.h
lldb_private::ScriptInterpreter::GetDataExtractorFromSBData
lldb::DataExtractorSP GetDataExtractorFromSBData(const lldb::SBData &data) const
Definition: ScriptInterpreter.cpp:78
lldb::eScriptLanguageNone
@ eScriptLanguageNone
Definition: lldb-enumerations.h:218
lldb_private::ScriptInterpreterIORedirect::ScriptInterpreterIORedirect
ScriptInterpreterIORedirect(std::unique_ptr< File > input, std::unique_ptr< File > output)
Definition: ScriptInterpreter.cpp:169
lldb_private::FileSpec
Definition: FileSpec.h:55
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
lldb_private::ScriptInterpreter::CollectDataForWatchpointCommandCallback
virtual void CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options, CommandReturnObject &result)
Definition: ScriptInterpreter.cpp:43
lldb_private::ThreadedCommunication::SetReadThreadBytesReceivedCallback
void SetReadThreadBytesReceivedCallback(ReadThreadBytesReceived callback, void *callback_baton)
Definition: ThreadedCommunication.cpp:341
lldb_private::CommandReturnObject::SetImmediateOutputFile
void SetImmediateOutputFile(lldb::FileSP file_sp)
Definition: CommandReturnObject.h:66
lldb_private::ScriptInterpreter::GetOpaqueTypeFromSBMemoryRegionInfo
llvm::Optional< MemoryRegionInfo > GetOpaqueTypeFromSBMemoryRegionInfo(const lldb::SBMemoryRegionInfo &mem_region) const
Definition: ScriptInterpreter.cpp:91
lldb_private::StructuredData::ObjectSP
std::shared_ptr< Object > ObjectSP
Definition: StructuredData.h:59
lldb_private::CommandReturnObject::GetOutputStream
Stream & GetOutputStream()
Definition: CommandReturnObject.h:46
lldb_private::WatchpointOptions
Definition: WatchpointOptions.h:25
lldb_private::ScriptInterpreterIORedirect::m_communication
ThreadedCommunication m_communication
Definition: ScriptInterpreter.h:122
lldb_private::BreakpointOptions
Definition: BreakpointOptions.h:27
lldb::eScriptLanguagePython
@ eScriptLanguagePython
Definition: lldb-enumerations.h:219
lldb_private::ScriptInterpreterIORedirect::m_disconnect
bool m_disconnect
Definition: ScriptInterpreter.h:123
Pipe.h
lldb_private::Debugger::GetInputFileSP
lldb::FileSP GetInputFileSP()
Definition: Debugger.h:135
ConnectionFileDescriptor.h
lldb_private::StructuredData::DictionarySP
std::shared_ptr< Dictionary > DictionarySP
Definition: StructuredData.h:67
lldb_private::File::eOpenOptionReadOnly
@ eOpenOptionReadOnly
Definition: File.h:50
lldb_private::Debugger
Definition: Debugger.h:74
lldb::eScriptLanguageUnknown
@ eScriptLanguageUnknown
Definition: lldb-enumerations.h:221
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:40
StringList.h
lldb_private::ScriptInterpreterIORedirect::~ScriptInterpreterIORedirect
~ScriptInterpreterIORedirect()
Definition: ScriptInterpreter.cpp:228
lldb_private::ThreadedCommunication::StartReadThread
virtual bool StartReadThread(Status *error_ptr=nullptr)
Starts a read thread whose sole purpose it to read bytes from the current connection.
Definition: ThreadedCommunication.cpp:158
lldb_private::File::eOpenOptionWriteOnly
@ eOpenOptionWriteOnly
Definition: File.h:51
lldb_private::Status
Definition: Status.h:44
lldb::SBData::m_opaque_sp
lldb::DataExtractorSP m_opaque_sp
Definition: SBData.h:159
lldb_private::CommandReturnObject
Definition: CommandReturnObject.h:26
lldb::SBMemoryRegionInfo::m_opaque_up
lldb::MemoryRegionInfoUP m_opaque_up
Definition: SBMemoryRegionInfo.h:133
lldb::SBData
Definition: SBData.h:20
lldb::SBMemoryRegionInfo
Definition: SBMemoryRegionInfo.h:17
lldb_private::ScriptInterpreter::LanguageToString
static std::string LanguageToString(lldb::ScriptLanguage language)
Definition: ScriptInterpreter.cpp:63
PseudoTerminal.h
lldb_private::CommandReturnObject::SetImmediateErrorFile
void SetImmediateErrorFile(lldb::FileSP file_sp)
Definition: CommandReturnObject.h:73
lldb_private::ScriptInterpreterIORedirect::Flush
void Flush()
Flush our output and error file handles.
Definition: ScriptInterpreter.cpp:221
lldb_private::ScriptInterpreter::AcquireInterpreterLock
virtual std::unique_ptr< ScriptInterpreterLocker > AcquireInterpreterLock()
Definition: ScriptInterpreter.cpp:135
lldb_private::ScriptInterpreter::GetInterpreterInfo
virtual StructuredData::DictionarySP GetInterpreterInfo()
Definition: ScriptInterpreter.cpp:49
lldb_private::FileSystem::Instance
static FileSystem & Instance()
Definition: common/FileSystem.cpp:46
lldb_private::ThreadedCommunication::Disconnect
lldb::ConnectionStatus Disconnect(Status *error_ptr=nullptr) override
Disconnect the communications connection if one is currently connected.
Definition: ThreadedCommunication.cpp:70
lldb_private::ScriptInterpreterIORedirect::m_input_file_sp
lldb::FileSP m_input_file_sp
Definition: ScriptInterpreter.h:119
Status.h
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::Stream::Write
size_t Write(const void *src, size_t src_len)
Output character bytes to the stream.
Definition: Stream.h:101
lldb::eScriptLanguageLua
@ eScriptLanguageLua
Definition: lldb-enumerations.h:220
lldb_private::LoadScriptOptions
Definition: ScriptInterpreter.h:75
lldb_private::StreamFile
Definition: StreamFile.h:22
Stream.h
lldb_private::CommandReturnObject::AppendError
void void AppendError(llvm::StringRef in_string)
Definition: CommandReturnObject.cpp:100
lldb_private::ScriptInterpreterIORedirect::m_output_file_sp
lldb::StreamFileSP m_output_file_sp
Definition: ScriptInterpreter.h:120
ScriptInterpreter.h
lldb_private::Debugger::GetErrorStream
StreamFile & GetErrorStream()
Definition: Debugger.h:149
lldb
Definition: SBAddress.h:15
lldb_private::ScriptInterpreter::CollectDataForBreakpointCommandCallback
virtual void CollectDataForBreakpointCommandCallback(std::vector< std::reference_wrapper< BreakpointOptions >> &options, CommandReturnObject &result)
Definition: ScriptInterpreter.cpp:36