1*480093f4SDimitry Andric //===-- ScriptInterpreterLua.cpp --------------------------------*- C++ -*-===// 2*480093f4SDimitry Andric // 3*480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*480093f4SDimitry Andric // 7*480093f4SDimitry Andric //===----------------------------------------------------------------------===// 8*480093f4SDimitry Andric 9*480093f4SDimitry Andric #include "ScriptInterpreterLua.h" 10*480093f4SDimitry Andric #include "Lua.h" 11*480093f4SDimitry Andric #include "lldb/Core/Debugger.h" 12*480093f4SDimitry Andric #include "lldb/Core/PluginManager.h" 13*480093f4SDimitry Andric #include "lldb/Core/StreamFile.h" 14*480093f4SDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h" 15*480093f4SDimitry Andric #include "lldb/Utility/Stream.h" 16*480093f4SDimitry Andric #include "lldb/Utility/StringList.h" 17*480093f4SDimitry Andric #include "lldb/Utility/Timer.h" 18*480093f4SDimitry Andric 19*480093f4SDimitry Andric using namespace lldb; 20*480093f4SDimitry Andric using namespace lldb_private; 21*480093f4SDimitry Andric 22*480093f4SDimitry Andric class IOHandlerLuaInterpreter : public IOHandlerDelegate, 23*480093f4SDimitry Andric public IOHandlerEditline { 24*480093f4SDimitry Andric public: 25*480093f4SDimitry Andric IOHandlerLuaInterpreter(Debugger &debugger, 26*480093f4SDimitry Andric ScriptInterpreterLua &script_interpreter) 27*480093f4SDimitry Andric : IOHandlerEditline(debugger, IOHandler::Type::LuaInterpreter, "lua", 28*480093f4SDimitry Andric ">>> ", "..> ", true, debugger.GetUseColor(), 0, 29*480093f4SDimitry Andric *this, nullptr), 30*480093f4SDimitry Andric m_script_interpreter(script_interpreter) { 31*480093f4SDimitry Andric llvm::cantFail(m_script_interpreter.EnterSession(debugger.GetID())); 32*480093f4SDimitry Andric } 33*480093f4SDimitry Andric 34*480093f4SDimitry Andric ~IOHandlerLuaInterpreter() { 35*480093f4SDimitry Andric llvm::cantFail(m_script_interpreter.LeaveSession()); 36*480093f4SDimitry Andric } 37*480093f4SDimitry Andric 38*480093f4SDimitry Andric void IOHandlerInputComplete(IOHandler &io_handler, 39*480093f4SDimitry Andric std::string &data) override { 40*480093f4SDimitry Andric if (llvm::Error error = m_script_interpreter.GetLua().Run(data)) { 41*480093f4SDimitry Andric *GetOutputStreamFileSP() << llvm::toString(std::move(error)); 42*480093f4SDimitry Andric } 43*480093f4SDimitry Andric } 44*480093f4SDimitry Andric 45*480093f4SDimitry Andric private: 46*480093f4SDimitry Andric ScriptInterpreterLua &m_script_interpreter; 47*480093f4SDimitry Andric }; 48*480093f4SDimitry Andric 49*480093f4SDimitry Andric ScriptInterpreterLua::ScriptInterpreterLua(Debugger &debugger) 50*480093f4SDimitry Andric : ScriptInterpreter(debugger, eScriptLanguageLua), 51*480093f4SDimitry Andric m_lua(std::make_unique<Lua>()) {} 52*480093f4SDimitry Andric 53*480093f4SDimitry Andric ScriptInterpreterLua::~ScriptInterpreterLua() {} 54*480093f4SDimitry Andric 55*480093f4SDimitry Andric bool ScriptInterpreterLua::ExecuteOneLine(llvm::StringRef command, 56*480093f4SDimitry Andric CommandReturnObject *result, 57*480093f4SDimitry Andric const ExecuteScriptOptions &options) { 58*480093f4SDimitry Andric if (llvm::Error e = m_lua->Run(command)) { 59*480093f4SDimitry Andric result->AppendErrorWithFormatv( 60*480093f4SDimitry Andric "lua failed attempting to evaluate '{0}': {1}\n", command, 61*480093f4SDimitry Andric llvm::toString(std::move(e))); 62*480093f4SDimitry Andric return false; 63*480093f4SDimitry Andric } 64*480093f4SDimitry Andric return true; 65*480093f4SDimitry Andric } 66*480093f4SDimitry Andric 67*480093f4SDimitry Andric void ScriptInterpreterLua::ExecuteInterpreterLoop() { 68*480093f4SDimitry Andric static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 69*480093f4SDimitry Andric Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION); 70*480093f4SDimitry Andric 71*480093f4SDimitry Andric Debugger &debugger = m_debugger; 72*480093f4SDimitry Andric 73*480093f4SDimitry Andric // At the moment, the only time the debugger does not have an input file 74*480093f4SDimitry Andric // handle is when this is called directly from lua, in which case it is 75*480093f4SDimitry Andric // both dangerous and unnecessary (not to mention confusing) to try to embed 76*480093f4SDimitry Andric // a running interpreter loop inside the already running lua interpreter 77*480093f4SDimitry Andric // loop, so we won't do it. 78*480093f4SDimitry Andric 79*480093f4SDimitry Andric if (!debugger.GetInputFile().IsValid()) 80*480093f4SDimitry Andric return; 81*480093f4SDimitry Andric 82*480093f4SDimitry Andric IOHandlerSP io_handler_sp(new IOHandlerLuaInterpreter(debugger, *this)); 83*480093f4SDimitry Andric debugger.PushIOHandler(io_handler_sp); 84*480093f4SDimitry Andric } 85*480093f4SDimitry Andric 86*480093f4SDimitry Andric bool ScriptInterpreterLua::LoadScriptingModule( 87*480093f4SDimitry Andric const char *filename, bool init_session, lldb_private::Status &error, 88*480093f4SDimitry Andric StructuredData::ObjectSP *module_sp) { 89*480093f4SDimitry Andric 90*480093f4SDimitry Andric if (llvm::Error e = m_lua->LoadModule(filename)) { 91*480093f4SDimitry Andric error.SetErrorStringWithFormatv("lua failed to import '{0}': {1}\n", 92*480093f4SDimitry Andric filename, llvm::toString(std::move(e))); 93*480093f4SDimitry Andric return false; 94*480093f4SDimitry Andric } 95*480093f4SDimitry Andric return true; 96*480093f4SDimitry Andric } 97*480093f4SDimitry Andric 98*480093f4SDimitry Andric void ScriptInterpreterLua::Initialize() { 99*480093f4SDimitry Andric static llvm::once_flag g_once_flag; 100*480093f4SDimitry Andric 101*480093f4SDimitry Andric llvm::call_once(g_once_flag, []() { 102*480093f4SDimitry Andric PluginManager::RegisterPlugin(GetPluginNameStatic(), 103*480093f4SDimitry Andric GetPluginDescriptionStatic(), 104*480093f4SDimitry Andric lldb::eScriptLanguageLua, CreateInstance); 105*480093f4SDimitry Andric }); 106*480093f4SDimitry Andric } 107*480093f4SDimitry Andric 108*480093f4SDimitry Andric void ScriptInterpreterLua::Terminate() {} 109*480093f4SDimitry Andric 110*480093f4SDimitry Andric llvm::Error ScriptInterpreterLua::EnterSession(user_id_t debugger_id) { 111*480093f4SDimitry Andric if (m_session_is_active) 112*480093f4SDimitry Andric return llvm::Error::success(); 113*480093f4SDimitry Andric 114*480093f4SDimitry Andric const char *fmt_str = 115*480093f4SDimitry Andric "lldb.debugger = lldb.SBDebugger.FindDebuggerWithID({0}); " 116*480093f4SDimitry Andric "lldb.target = lldb.debugger:GetSelectedTarget(); " 117*480093f4SDimitry Andric "lldb.process = lldb.target:GetProcess(); " 118*480093f4SDimitry Andric "lldb.thread = lldb.process:GetSelectedThread(); " 119*480093f4SDimitry Andric "lldb.frame = lldb.thread:GetSelectedFrame()"; 120*480093f4SDimitry Andric return m_lua->Run(llvm::formatv(fmt_str, debugger_id).str()); 121*480093f4SDimitry Andric } 122*480093f4SDimitry Andric 123*480093f4SDimitry Andric llvm::Error ScriptInterpreterLua::LeaveSession() { 124*480093f4SDimitry Andric if (!m_session_is_active) 125*480093f4SDimitry Andric return llvm::Error::success(); 126*480093f4SDimitry Andric 127*480093f4SDimitry Andric m_session_is_active = false; 128*480093f4SDimitry Andric 129*480093f4SDimitry Andric llvm::StringRef str = "lldb.debugger = nil; " 130*480093f4SDimitry Andric "lldb.target = nil; " 131*480093f4SDimitry Andric "lldb.process = nil; " 132*480093f4SDimitry Andric "lldb.thread = nil; " 133*480093f4SDimitry Andric "lldb.frame = nil"; 134*480093f4SDimitry Andric return m_lua->Run(str); 135*480093f4SDimitry Andric } 136*480093f4SDimitry Andric 137*480093f4SDimitry Andric lldb::ScriptInterpreterSP 138*480093f4SDimitry Andric ScriptInterpreterLua::CreateInstance(Debugger &debugger) { 139*480093f4SDimitry Andric return std::make_shared<ScriptInterpreterLua>(debugger); 140*480093f4SDimitry Andric } 141*480093f4SDimitry Andric 142*480093f4SDimitry Andric lldb_private::ConstString ScriptInterpreterLua::GetPluginNameStatic() { 143*480093f4SDimitry Andric static ConstString g_name("script-lua"); 144*480093f4SDimitry Andric return g_name; 145*480093f4SDimitry Andric } 146*480093f4SDimitry Andric 147*480093f4SDimitry Andric const char *ScriptInterpreterLua::GetPluginDescriptionStatic() { 148*480093f4SDimitry Andric return "Lua script interpreter"; 149*480093f4SDimitry Andric } 150*480093f4SDimitry Andric 151*480093f4SDimitry Andric lldb_private::ConstString ScriptInterpreterLua::GetPluginName() { 152*480093f4SDimitry Andric return GetPluginNameStatic(); 153*480093f4SDimitry Andric } 154*480093f4SDimitry Andric 155*480093f4SDimitry Andric uint32_t ScriptInterpreterLua::GetPluginVersion() { return 1; } 156*480093f4SDimitry Andric 157*480093f4SDimitry Andric Lua &ScriptInterpreterLua::GetLua() { return *m_lua; } 158