brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.3 KiB · d2fd372 Raw
310 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Interpreter/ScriptInterpreter.h"10#include "lldb/Core/Debugger.h"11#include "lldb/Host/ConnectionFileDescriptor.h"12#include "lldb/Host/Pipe.h"13#include "lldb/Host/PseudoTerminal.h"14#include "lldb/Interpreter/CommandReturnObject.h"15#include "lldb/Utility/Status.h"16#include "lldb/Utility/Stream.h"17#include "lldb/Utility/StringList.h"18#if defined(_WIN32)19#include "lldb/Host/windows/ConnectionGenericFileWindows.h"20#endif21#include <cstdio>22#include <cstdlib>23#include <memory>24#include <optional>25#include <string>26 27using namespace lldb;28using namespace lldb_private;29 30ScriptInterpreter::ScriptInterpreter(Debugger &debugger,31                                     lldb::ScriptLanguage script_lang)32    : m_debugger(debugger), m_script_lang(script_lang) {}33 34void ScriptInterpreter::CollectDataForBreakpointCommandCallback(35    std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,36    CommandReturnObject &result) {37  result.AppendError(38      "This script interpreter does not support breakpoint callbacks.");39}40 41void ScriptInterpreter::CollectDataForWatchpointCommandCallback(42    WatchpointOptions *bp_options, CommandReturnObject &result) {43  result.AppendError(44      "This script interpreter does not support watchpoint callbacks.");45}46 47StructuredData::DictionarySP ScriptInterpreter::GetInterpreterInfo() {48  return nullptr;49}50 51bool ScriptInterpreter::LoadScriptingModule(52    const char *filename, const LoadScriptOptions &options,53    lldb_private::Status &error, StructuredData::ObjectSP *module_sp,54    FileSpec extra_search_dir, lldb::TargetSP loaded_into_target_sp) {55  error = Status::FromErrorString(56      "This script interpreter does not support importing modules.");57  return false;58}59 60std::string ScriptInterpreter::LanguageToString(lldb::ScriptLanguage language) {61  switch (language) {62  case eScriptLanguageNone:63    return "None";64  case eScriptLanguagePython:65    return "Python";66  case eScriptLanguageLua:67    return "Lua";68  case eScriptLanguageUnknown:69    return "Unknown";70  }71  llvm_unreachable("Unhandled ScriptInterpreter!");72}73 74lldb::DataExtractorSP75ScriptInterpreter::GetDataExtractorFromSBData(const lldb::SBData &data) const {76  return data.m_opaque_sp;77}78 79lldb::BreakpointSP ScriptInterpreter::GetOpaqueTypeFromSBBreakpoint(80    const lldb::SBBreakpoint &breakpoint) const {81  return breakpoint.m_opaque_wp.lock();82}83 84lldb::BreakpointLocationSP85ScriptInterpreter::GetOpaqueTypeFromSBBreakpointLocation(86    const lldb::SBBreakpointLocation &break_loc) const {87  return break_loc.m_opaque_wp.lock();88}89 90lldb::ProcessAttachInfoSP ScriptInterpreter::GetOpaqueTypeFromSBAttachInfo(91    const lldb::SBAttachInfo &attach_info) const {92  return attach_info.m_opaque_sp;93}94 95lldb::ProcessLaunchInfoSP ScriptInterpreter::GetOpaqueTypeFromSBLaunchInfo(96    const lldb::SBLaunchInfo &launch_info) const {97  return std::make_shared<ProcessLaunchInfo>(98      *reinterpret_cast<ProcessLaunchInfo *>(launch_info.m_opaque_sp.get()));99}100 101Status102ScriptInterpreter::GetStatusFromSBError(const lldb::SBError &error) const {103  if (error.m_opaque_up)104    return error.m_opaque_up->Clone();105 106  return Status();107}108 109lldb::StackFrameSP110ScriptInterpreter::GetOpaqueTypeFromSBFrame(const lldb::SBFrame &frame) const {111  if (frame.m_opaque_sp)112    return frame.m_opaque_sp->GetFrameSP();113  return nullptr;114}115 116Event *117ScriptInterpreter::GetOpaqueTypeFromSBEvent(const lldb::SBEvent &event) const {118  return event.m_opaque_ptr;119}120 121lldb::StreamSP ScriptInterpreter::GetOpaqueTypeFromSBStream(122    const lldb::SBStream &stream) const {123  if (stream.m_opaque_up) {124    lldb::StreamSP s = std::make_shared<lldb_private::StreamString>();125    *s << reinterpret_cast<StreamString *>(stream.m_opaque_up.get())->m_packet;126    return s;127  }128 129  return nullptr;130}131 132SymbolContext ScriptInterpreter::GetOpaqueTypeFromSBSymbolContext(133    const lldb::SBSymbolContext &sb_sym_ctx) const {134  if (sb_sym_ctx.m_opaque_up)135    return *sb_sym_ctx.m_opaque_up;136  return {};137}138 139std::optional<lldb_private::MemoryRegionInfo>140ScriptInterpreter::GetOpaqueTypeFromSBMemoryRegionInfo(141    const lldb::SBMemoryRegionInfo &mem_region) const {142  if (!mem_region.m_opaque_up)143    return std::nullopt;144  return *mem_region.m_opaque_up.get();145}146 147lldb::ExecutionContextRefSP148ScriptInterpreter::GetOpaqueTypeFromSBExecutionContext(149    const lldb::SBExecutionContext &exe_ctx) const {150  return exe_ctx.m_exe_ctx_sp;151}152 153lldb::StackFrameListSP ScriptInterpreter::GetOpaqueTypeFromSBFrameList(154    const lldb::SBFrameList &frame_list) const {155  return frame_list.m_opaque_sp;156}157 158lldb::ScriptLanguage159ScriptInterpreter::StringToLanguage(const llvm::StringRef &language) {160  if (language.equals_insensitive(LanguageToString(eScriptLanguageNone)))161    return eScriptLanguageNone;162  if (language.equals_insensitive(LanguageToString(eScriptLanguagePython)))163    return eScriptLanguagePython;164  if (language.equals_insensitive(LanguageToString(eScriptLanguageLua)))165    return eScriptLanguageLua;166  return eScriptLanguageUnknown;167}168 169Status ScriptInterpreter::SetBreakpointCommandCallback(170    std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,171    const char *callback_text) {172  Status error;173  for (BreakpointOptions &bp_options : bp_options_vec) {174    error = SetBreakpointCommandCallback(bp_options, callback_text,175                                         /*is_callback=*/false);176    if (!error.Success())177      break;178  }179  return error;180}181 182Status ScriptInterpreter::SetBreakpointCommandCallbackFunction(183    std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,184    const char *function_name, StructuredData::ObjectSP extra_args_sp) {185  Status error;186  for (BreakpointOptions &bp_options : bp_options_vec) {187    error = SetBreakpointCommandCallbackFunction(bp_options, function_name,188                                                 extra_args_sp);189    if (!error.Success())190      return error;191  }192  return error;193}194 195std::unique_ptr<ScriptInterpreterLocker>196ScriptInterpreter::AcquireInterpreterLock() {197  return std::make_unique<ScriptInterpreterLocker>();198}199 200static void ReadThreadBytesReceived(void *baton, const void *src,201                                    size_t src_len) {202  if (src && src_len) {203    Stream *strm = (Stream *)baton;204    strm->Write(src, src_len);205    strm->Flush();206  }207}208 209llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>210ScriptInterpreterIORedirect::Create(bool enable_io, Debugger &debugger,211                                    CommandReturnObject *result) {212  if (enable_io)213    return std::unique_ptr<ScriptInterpreterIORedirect>(214        new ScriptInterpreterIORedirect(debugger, result));215 216  auto nullin = FileSystem::Instance().Open(FileSpec(FileSystem::DEV_NULL),217                                            File::eOpenOptionReadOnly);218  if (!nullin)219    return nullin.takeError();220 221  auto nullout = FileSystem::Instance().Open(FileSpec(FileSystem::DEV_NULL),222                                             File::eOpenOptionWriteOnly);223  if (!nullout)224    return nullin.takeError();225 226  return std::unique_ptr<ScriptInterpreterIORedirect>(227      new ScriptInterpreterIORedirect(std::move(*nullin), std::move(*nullout)));228}229 230ScriptInterpreterIORedirect::ScriptInterpreterIORedirect(231    std::unique_ptr<File> input, std::unique_ptr<File> output)232    : m_input_file_sp(std::move(input)),233      m_output_file_sp(std::make_shared<LockableStreamFile>(std::move(output),234                                                            m_output_mutex)),235      m_error_file_sp(m_output_file_sp),236      m_communication("lldb.ScriptInterpreterIORedirect.comm"),237      m_disconnect(false) {}238 239ScriptInterpreterIORedirect::ScriptInterpreterIORedirect(240    Debugger &debugger, CommandReturnObject *result)241    : m_communication("lldb.ScriptInterpreterIORedirect.comm"),242      m_disconnect(false) {243 244  if (result) {245    m_input_file_sp = debugger.GetInputFileSP();246 247    Pipe pipe;248    Status pipe_result = pipe.CreateNew();249#if defined(_WIN32)250    lldb::file_t read_file = pipe.GetReadNativeHandle();251    pipe.ReleaseReadFileDescriptor();252    std::unique_ptr<ConnectionGenericFile> conn_up =253        std::make_unique<ConnectionGenericFile>(read_file, true);254#else255    std::unique_ptr<ConnectionFileDescriptor> conn_up =256        std::make_unique<ConnectionFileDescriptor>(257            pipe.ReleaseReadFileDescriptor(), true);258#endif259 260    if (conn_up->IsConnected()) {261      m_communication.SetConnection(std::move(conn_up));262      m_communication.SetReadThreadBytesReceivedCallback(263          ReadThreadBytesReceived, &result->GetOutputStream());264      m_communication.StartReadThread();265      m_disconnect = true;266 267      FILE *outfile_handle = fdopen(pipe.ReleaseWriteFileDescriptor(), "w");268      m_output_file_sp = std::make_shared<LockableStreamFile>(269          std::make_shared<StreamFile>(outfile_handle, NativeFile::Owned),270          m_output_mutex);271      m_error_file_sp = m_output_file_sp;272      if (outfile_handle)273        ::setbuf(outfile_handle, nullptr);274 275      result->SetImmediateOutputFile(debugger.GetOutputFileSP());276      result->SetImmediateErrorFile(debugger.GetErrorFileSP());277    }278  }279 280  if (!m_input_file_sp || !m_output_file_sp || !m_error_file_sp)281    debugger.AdoptTopIOHandlerFilesIfInvalid(m_input_file_sp, m_output_file_sp,282                                             m_error_file_sp);283}284 285void ScriptInterpreterIORedirect::Flush() {286  if (m_output_file_sp)287    m_output_file_sp->Lock().Flush();288  if (m_error_file_sp)289    m_error_file_sp->Lock().Flush();290}291 292ScriptInterpreterIORedirect::~ScriptInterpreterIORedirect() {293  if (!m_disconnect)294    return;295 296  assert(m_output_file_sp);297  assert(m_error_file_sp);298  assert(m_output_file_sp == m_error_file_sp);299 300  // Close the write end of the pipe since we are done with our one line301  // script. This should cause the read thread that output_comm is using to302  // exit.303  m_output_file_sp->GetUnlockedFile().Close();304  // The close above should cause this thread to exit when it gets to the end305  // of file, so let it get all its data.306  m_communication.JoinReadThread();307  // Now we can close the read end of the pipe.308  m_communication.Disconnect();309}310