Path: blob/main/contrib/llvm-project/lldb/source/Interpreter/ScriptInterpreter.cpp
39587 views
//===-- ScriptInterpreter.cpp ---------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/Interpreter/ScriptInterpreter.h"9#include "lldb/Core/Debugger.h"10#include "lldb/Host/ConnectionFileDescriptor.h"11#include "lldb/Host/Pipe.h"12#include "lldb/Host/PseudoTerminal.h"13#include "lldb/Interpreter/CommandReturnObject.h"14#include "lldb/Utility/Status.h"15#include "lldb/Utility/Stream.h"16#include "lldb/Utility/StringList.h"17#if defined(_WIN32)18#include "lldb/Host/windows/ConnectionGenericFileWindows.h"19#endif20#include <cstdio>21#include <cstdlib>22#include <memory>23#include <optional>24#include <string>2526using namespace lldb;27using namespace lldb_private;2829ScriptInterpreter::ScriptInterpreter(Debugger &debugger,30lldb::ScriptLanguage script_lang)31: m_debugger(debugger), m_script_lang(script_lang) {}3233void ScriptInterpreter::CollectDataForBreakpointCommandCallback(34std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,35CommandReturnObject &result) {36result.AppendError(37"This script interpreter does not support breakpoint callbacks.");38}3940void ScriptInterpreter::CollectDataForWatchpointCommandCallback(41WatchpointOptions *bp_options, CommandReturnObject &result) {42result.AppendError(43"This script interpreter does not support watchpoint callbacks.");44}4546StructuredData::DictionarySP ScriptInterpreter::GetInterpreterInfo() {47return nullptr;48}4950bool ScriptInterpreter::LoadScriptingModule(const char *filename,51const LoadScriptOptions &options,52lldb_private::Status &error,53StructuredData::ObjectSP *module_sp,54FileSpec extra_search_dir) {55error.SetErrorString(56"This script interpreter does not support importing modules.");57return false;58}5960std::string ScriptInterpreter::LanguageToString(lldb::ScriptLanguage language) {61switch (language) {62case eScriptLanguageNone:63return "None";64case eScriptLanguagePython:65return "Python";66case eScriptLanguageLua:67return "Lua";68case eScriptLanguageUnknown:69return "Unknown";70}71llvm_unreachable("Unhandled ScriptInterpreter!");72}7374lldb::DataExtractorSP75ScriptInterpreter::GetDataExtractorFromSBData(const lldb::SBData &data) const {76return data.m_opaque_sp;77}7879lldb::BreakpointSP ScriptInterpreter::GetOpaqueTypeFromSBBreakpoint(80const lldb::SBBreakpoint &breakpoint) const {81return breakpoint.m_opaque_wp.lock();82}8384lldb::ProcessAttachInfoSP ScriptInterpreter::GetOpaqueTypeFromSBAttachInfo(85const lldb::SBAttachInfo &attach_info) const {86return attach_info.m_opaque_sp;87}8889lldb::ProcessLaunchInfoSP ScriptInterpreter::GetOpaqueTypeFromSBLaunchInfo(90const lldb::SBLaunchInfo &launch_info) const {91return std::make_shared<ProcessLaunchInfo>(92*reinterpret_cast<ProcessLaunchInfo *>(launch_info.m_opaque_sp.get()));93}9495Status96ScriptInterpreter::GetStatusFromSBError(const lldb::SBError &error) const {97if (error.m_opaque_up)98return *error.m_opaque_up;99100return Status();101}102103Event *104ScriptInterpreter::GetOpaqueTypeFromSBEvent(const lldb::SBEvent &event) const {105return event.m_opaque_ptr;106}107108lldb::StreamSP ScriptInterpreter::GetOpaqueTypeFromSBStream(109const lldb::SBStream &stream) const {110if (stream.m_opaque_up) {111lldb::StreamSP s = std::make_shared<lldb_private::StreamString>();112*s << reinterpret_cast<StreamString *>(stream.m_opaque_up.get())->m_packet;113return s;114}115116return nullptr;117}118119std::optional<MemoryRegionInfo>120ScriptInterpreter::GetOpaqueTypeFromSBMemoryRegionInfo(121const lldb::SBMemoryRegionInfo &mem_region) const {122if (!mem_region.m_opaque_up)123return std::nullopt;124return *mem_region.m_opaque_up.get();125}126127lldb::ScriptLanguage128ScriptInterpreter::StringToLanguage(const llvm::StringRef &language) {129if (language.equals_insensitive(LanguageToString(eScriptLanguageNone)))130return eScriptLanguageNone;131if (language.equals_insensitive(LanguageToString(eScriptLanguagePython)))132return eScriptLanguagePython;133if (language.equals_insensitive(LanguageToString(eScriptLanguageLua)))134return eScriptLanguageLua;135return eScriptLanguageUnknown;136}137138Status ScriptInterpreter::SetBreakpointCommandCallback(139std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,140const char *callback_text) {141Status error;142for (BreakpointOptions &bp_options : bp_options_vec) {143error = SetBreakpointCommandCallback(bp_options, callback_text,144/*is_callback=*/false);145if (!error.Success())146break;147}148return error;149}150151Status ScriptInterpreter::SetBreakpointCommandCallbackFunction(152std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,153const char *function_name, StructuredData::ObjectSP extra_args_sp) {154Status error;155for (BreakpointOptions &bp_options : bp_options_vec) {156error = SetBreakpointCommandCallbackFunction(bp_options, function_name,157extra_args_sp);158if (!error.Success())159return error;160}161return error;162}163164std::unique_ptr<ScriptInterpreterLocker>165ScriptInterpreter::AcquireInterpreterLock() {166return std::make_unique<ScriptInterpreterLocker>();167}168169static void ReadThreadBytesReceived(void *baton, const void *src,170size_t src_len) {171if (src && src_len) {172Stream *strm = (Stream *)baton;173strm->Write(src, src_len);174strm->Flush();175}176}177178llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>179ScriptInterpreterIORedirect::Create(bool enable_io, Debugger &debugger,180CommandReturnObject *result) {181if (enable_io)182return std::unique_ptr<ScriptInterpreterIORedirect>(183new ScriptInterpreterIORedirect(debugger, result));184185auto nullin = FileSystem::Instance().Open(FileSpec(FileSystem::DEV_NULL),186File::eOpenOptionReadOnly);187if (!nullin)188return nullin.takeError();189190auto nullout = FileSystem::Instance().Open(FileSpec(FileSystem::DEV_NULL),191File::eOpenOptionWriteOnly);192if (!nullout)193return nullin.takeError();194195return std::unique_ptr<ScriptInterpreterIORedirect>(196new ScriptInterpreterIORedirect(std::move(*nullin), std::move(*nullout)));197}198199ScriptInterpreterIORedirect::ScriptInterpreterIORedirect(200std::unique_ptr<File> input, std::unique_ptr<File> output)201: m_input_file_sp(std::move(input)),202m_output_file_sp(std::make_shared<StreamFile>(std::move(output))),203m_error_file_sp(m_output_file_sp),204m_communication("lldb.ScriptInterpreterIORedirect.comm"),205m_disconnect(false) {}206207ScriptInterpreterIORedirect::ScriptInterpreterIORedirect(208Debugger &debugger, CommandReturnObject *result)209: m_communication("lldb.ScriptInterpreterIORedirect.comm"),210m_disconnect(false) {211212if (result) {213m_input_file_sp = debugger.GetInputFileSP();214215Pipe pipe;216Status pipe_result = pipe.CreateNew(false);217#if defined(_WIN32)218lldb::file_t read_file = pipe.GetReadNativeHandle();219pipe.ReleaseReadFileDescriptor();220std::unique_ptr<ConnectionGenericFile> conn_up =221std::make_unique<ConnectionGenericFile>(read_file, true);222#else223std::unique_ptr<ConnectionFileDescriptor> conn_up =224std::make_unique<ConnectionFileDescriptor>(225pipe.ReleaseReadFileDescriptor(), true);226#endif227228if (conn_up->IsConnected()) {229m_communication.SetConnection(std::move(conn_up));230m_communication.SetReadThreadBytesReceivedCallback(231ReadThreadBytesReceived, &result->GetOutputStream());232m_communication.StartReadThread();233m_disconnect = true;234235FILE *outfile_handle = fdopen(pipe.ReleaseWriteFileDescriptor(), "w");236m_output_file_sp = std::make_shared<StreamFile>(outfile_handle, true);237m_error_file_sp = m_output_file_sp;238if (outfile_handle)239::setbuf(outfile_handle, nullptr);240241result->SetImmediateOutputFile(debugger.GetOutputStream().GetFileSP());242result->SetImmediateErrorFile(debugger.GetErrorStream().GetFileSP());243}244}245246if (!m_input_file_sp || !m_output_file_sp || !m_error_file_sp)247debugger.AdoptTopIOHandlerFilesIfInvalid(m_input_file_sp, m_output_file_sp,248m_error_file_sp);249}250251void ScriptInterpreterIORedirect::Flush() {252if (m_output_file_sp)253m_output_file_sp->Flush();254if (m_error_file_sp)255m_error_file_sp->Flush();256}257258ScriptInterpreterIORedirect::~ScriptInterpreterIORedirect() {259if (!m_disconnect)260return;261262assert(m_output_file_sp);263assert(m_error_file_sp);264assert(m_output_file_sp == m_error_file_sp);265266// Close the write end of the pipe since we are done with our one line267// script. This should cause the read thread that output_comm is using to268// exit.269m_output_file_sp->GetFile().Close();270// The close above should cause this thread to exit when it gets to the end271// of file, so let it get all its data.272m_communication.JoinReadThread();273// Now we can close the read end of the pipe.274m_communication.Disconnect();275}276277278