180814287SRaphael Isemann //===-- ScriptInterpreterLua.cpp ------------------------------------------===//
267de8962SJonas Devlieghere //
367de8962SJonas Devlieghere // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
467de8962SJonas Devlieghere // See https://llvm.org/LICENSE.txt for license information.
567de8962SJonas Devlieghere // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
667de8962SJonas Devlieghere //
767de8962SJonas Devlieghere //===----------------------------------------------------------------------===//
867de8962SJonas Devlieghere
967de8962SJonas Devlieghere #include "ScriptInterpreterLua.h"
1028613242SJonas Devlieghere #include "Lua.h"
11a0d7406aSPedro Tammela #include "lldb/Breakpoint/StoppointCallbackContext.h"
1267de8962SJonas Devlieghere #include "lldb/Core/Debugger.h"
1367de8962SJonas Devlieghere #include "lldb/Core/PluginManager.h"
1467de8962SJonas Devlieghere #include "lldb/Core/StreamFile.h"
1528613242SJonas Devlieghere #include "lldb/Interpreter/CommandReturnObject.h"
16a0d7406aSPedro Tammela #include "lldb/Target/ExecutionContext.h"
1767de8962SJonas Devlieghere #include "lldb/Utility/Stream.h"
1867de8962SJonas Devlieghere #include "lldb/Utility/StringList.h"
1928613242SJonas Devlieghere #include "lldb/Utility/Timer.h"
20d853bd7aSPedro Tammela #include "llvm/ADT/StringRef.h"
21ed8184b7SJonas Devlieghere #include "llvm/Support/FormatAdapters.h"
22a0d7406aSPedro Tammela #include <memory>
23d853bd7aSPedro Tammela #include <vector>
2467de8962SJonas Devlieghere
2567de8962SJonas Devlieghere using namespace lldb;
2667de8962SJonas Devlieghere using namespace lldb_private;
2767de8962SJonas Devlieghere
28bba9ba8dSJonas Devlieghere LLDB_PLUGIN_DEFINE(ScriptInterpreterLua)
29fbb4d1e4SJonas Devlieghere
30d853bd7aSPedro Tammela enum ActiveIOHandler {
31d853bd7aSPedro Tammela eIOHandlerNone,
32d853bd7aSPedro Tammela eIOHandlerBreakpoint,
33d853bd7aSPedro Tammela eIOHandlerWatchpoint
34d853bd7aSPedro Tammela };
35d853bd7aSPedro Tammela
3628613242SJonas Devlieghere class IOHandlerLuaInterpreter : public IOHandlerDelegate,
3728613242SJonas Devlieghere public IOHandlerEditline {
3828613242SJonas Devlieghere public:
IOHandlerLuaInterpreter(Debugger & debugger,ScriptInterpreterLua & script_interpreter,ActiveIOHandler active_io_handler=eIOHandlerNone)394164be72SJonas Devlieghere IOHandlerLuaInterpreter(Debugger &debugger,
40d853bd7aSPedro Tammela ScriptInterpreterLua &script_interpreter,
41d853bd7aSPedro Tammela ActiveIOHandler active_io_handler = eIOHandlerNone)
4228613242SJonas Devlieghere : IOHandlerEditline(debugger, IOHandler::Type::LuaInterpreter, "lua",
4328613242SJonas Devlieghere ">>> ", "..> ", true, debugger.GetUseColor(), 0,
4428613242SJonas Devlieghere *this, nullptr),
45d853bd7aSPedro Tammela m_script_interpreter(script_interpreter),
46d853bd7aSPedro Tammela m_active_io_handler(active_io_handler) {
47fa1b4a96SJonas Devlieghere llvm::cantFail(m_script_interpreter.GetLua().ChangeIO(
48fa1b4a96SJonas Devlieghere debugger.GetOutputFile().GetStream(),
49fa1b4a96SJonas Devlieghere debugger.GetErrorFile().GetStream()));
5045c971f7SJonas Devlieghere llvm::cantFail(m_script_interpreter.EnterSession(debugger.GetID()));
5145c971f7SJonas Devlieghere }
5245c971f7SJonas Devlieghere
~IOHandlerLuaInterpreter()535ddd4fc5SJonas Devlieghere ~IOHandlerLuaInterpreter() override {
5445c971f7SJonas Devlieghere llvm::cantFail(m_script_interpreter.LeaveSession());
5545c971f7SJonas Devlieghere }
5628613242SJonas Devlieghere
IOHandlerActivated(IOHandler & io_handler,bool interactive)57d853bd7aSPedro Tammela void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
58d853bd7aSPedro Tammela const char *instructions = nullptr;
59d853bd7aSPedro Tammela switch (m_active_io_handler) {
60d853bd7aSPedro Tammela case eIOHandlerNone:
61e81ba283SSiger Yang break;
62d853bd7aSPedro Tammela case eIOHandlerWatchpoint:
63e81ba283SSiger Yang instructions = "Enter your Lua command(s). Type 'quit' to end.\n"
64e81ba283SSiger Yang "The commands are compiled as the body of the following "
65e81ba283SSiger Yang "Lua function\n"
66e81ba283SSiger Yang "function (frame, wp) end\n";
67e81ba283SSiger Yang SetPrompt(llvm::StringRef("..> "));
68d853bd7aSPedro Tammela break;
69d853bd7aSPedro Tammela case eIOHandlerBreakpoint:
70d853bd7aSPedro Tammela instructions = "Enter your Lua command(s). Type 'quit' to end.\n"
71d853bd7aSPedro Tammela "The commands are compiled as the body of the following "
72d853bd7aSPedro Tammela "Lua function\n"
73d853bd7aSPedro Tammela "function (frame, bp_loc, ...) end\n";
74d853bd7aSPedro Tammela SetPrompt(llvm::StringRef("..> "));
75d853bd7aSPedro Tammela break;
76d853bd7aSPedro Tammela }
77d853bd7aSPedro Tammela if (instructions == nullptr)
78d853bd7aSPedro Tammela return;
79d853bd7aSPedro Tammela if (interactive)
80d853bd7aSPedro Tammela *io_handler.GetOutputStreamFileSP() << instructions;
81d853bd7aSPedro Tammela }
82d853bd7aSPedro Tammela
IOHandlerIsInputComplete(IOHandler & io_handler,StringList & lines)83d853bd7aSPedro Tammela bool IOHandlerIsInputComplete(IOHandler &io_handler,
84d853bd7aSPedro Tammela StringList &lines) override {
85d853bd7aSPedro Tammela size_t last = lines.GetSize() - 1;
86d853bd7aSPedro Tammela if (IsQuitCommand(lines.GetStringAtIndex(last))) {
87e81ba283SSiger Yang if (m_active_io_handler == eIOHandlerBreakpoint ||
88e81ba283SSiger Yang m_active_io_handler == eIOHandlerWatchpoint)
89d853bd7aSPedro Tammela lines.DeleteStringAtIndex(last);
90d853bd7aSPedro Tammela return true;
91d853bd7aSPedro Tammela }
92d853bd7aSPedro Tammela StreamString str;
93d853bd7aSPedro Tammela lines.Join("\n", str);
94d853bd7aSPedro Tammela if (llvm::Error E =
95d853bd7aSPedro Tammela m_script_interpreter.GetLua().CheckSyntax(str.GetString())) {
96d853bd7aSPedro Tammela std::string error_str = toString(std::move(E));
97d853bd7aSPedro Tammela // Lua always errors out to incomplete code with '<eof>'
98d853bd7aSPedro Tammela return error_str.find("<eof>") == std::string::npos;
99d853bd7aSPedro Tammela }
100e81ba283SSiger Yang // The breakpoint and watchpoint handler only exits with a explicit 'quit'
101e81ba283SSiger Yang return m_active_io_handler != eIOHandlerBreakpoint &&
102e81ba283SSiger Yang m_active_io_handler != eIOHandlerWatchpoint;
103d853bd7aSPedro Tammela }
104d853bd7aSPedro Tammela
IOHandlerInputComplete(IOHandler & io_handler,std::string & data)10528613242SJonas Devlieghere void IOHandlerInputComplete(IOHandler &io_handler,
10628613242SJonas Devlieghere std::string &data) override {
107d853bd7aSPedro Tammela switch (m_active_io_handler) {
108d853bd7aSPedro Tammela case eIOHandlerBreakpoint: {
109cfb96d84SJim Ingham auto *bp_options_vec =
110cfb96d84SJim Ingham static_cast<std::vector<std::reference_wrapper<BreakpointOptions>> *>(
111d853bd7aSPedro Tammela io_handler.GetUserData());
112cfb96d84SJim Ingham for (BreakpointOptions &bp_options : *bp_options_vec) {
113d853bd7aSPedro Tammela Status error = m_script_interpreter.SetBreakpointCommandCallback(
114d853bd7aSPedro Tammela bp_options, data.c_str());
115d853bd7aSPedro Tammela if (error.Fail())
116d853bd7aSPedro Tammela *io_handler.GetErrorStreamFileSP() << error.AsCString() << '\n';
117d853bd7aSPedro Tammela }
118d853bd7aSPedro Tammela io_handler.SetIsDone(true);
119d853bd7aSPedro Tammela } break;
120e81ba283SSiger Yang case eIOHandlerWatchpoint: {
121e81ba283SSiger Yang auto *wp_options =
122e81ba283SSiger Yang static_cast<WatchpointOptions *>(io_handler.GetUserData());
123e81ba283SSiger Yang m_script_interpreter.SetWatchpointCommandCallback(wp_options,
124e81ba283SSiger Yang data.c_str());
125d853bd7aSPedro Tammela io_handler.SetIsDone(true);
126e81ba283SSiger Yang } break;
127d853bd7aSPedro Tammela case eIOHandlerNone:
128d853bd7aSPedro Tammela if (IsQuitCommand(data)) {
1291728dec2SJonas Devlieghere io_handler.SetIsDone(true);
1301728dec2SJonas Devlieghere return;
1311728dec2SJonas Devlieghere }
132d853bd7aSPedro Tammela if (llvm::Error error = m_script_interpreter.GetLua().Run(data))
133d853bd7aSPedro Tammela *io_handler.GetErrorStreamFileSP() << toString(std::move(error));
134d853bd7aSPedro Tammela break;
13528613242SJonas Devlieghere }
13628613242SJonas Devlieghere }
13728613242SJonas Devlieghere
13828613242SJonas Devlieghere private:
1394164be72SJonas Devlieghere ScriptInterpreterLua &m_script_interpreter;
140d853bd7aSPedro Tammela ActiveIOHandler m_active_io_handler;
141d853bd7aSPedro Tammela
IsQuitCommand(llvm::StringRef cmd)142d853bd7aSPedro Tammela bool IsQuitCommand(llvm::StringRef cmd) { return cmd.rtrim() == "quit"; }
14328613242SJonas Devlieghere };
14428613242SJonas Devlieghere
ScriptInterpreterLua(Debugger & debugger)14567de8962SJonas Devlieghere ScriptInterpreterLua::ScriptInterpreterLua(Debugger &debugger)
1464164be72SJonas Devlieghere : ScriptInterpreter(debugger, eScriptLanguageLua),
1474164be72SJonas Devlieghere m_lua(std::make_unique<Lua>()) {}
14867de8962SJonas Devlieghere
149fd2433e1SJonas Devlieghere ScriptInterpreterLua::~ScriptInterpreterLua() = default;
15067de8962SJonas Devlieghere
GetInterpreterInfo()151*bbef51ebSLawrence D'Anna StructuredData::DictionarySP ScriptInterpreterLua::GetInterpreterInfo() {
152*bbef51ebSLawrence D'Anna auto info = std::make_shared<StructuredData::Dictionary>();
153*bbef51ebSLawrence D'Anna info->AddStringItem("language", "lua");
154*bbef51ebSLawrence D'Anna return info;
155*bbef51ebSLawrence D'Anna }
156*bbef51ebSLawrence D'Anna
ExecuteOneLine(llvm::StringRef command,CommandReturnObject * result,const ExecuteScriptOptions & options)15767de8962SJonas Devlieghere bool ScriptInterpreterLua::ExecuteOneLine(llvm::StringRef command,
15828613242SJonas Devlieghere CommandReturnObject *result,
15928613242SJonas Devlieghere const ExecuteScriptOptions &options) {
160ed8184b7SJonas Devlieghere if (command.empty()) {
161ed8184b7SJonas Devlieghere if (result)
162ed8184b7SJonas Devlieghere result->AppendError("empty command passed to lua\n");
163ed8184b7SJonas Devlieghere return false;
164ed8184b7SJonas Devlieghere }
165ed8184b7SJonas Devlieghere
166ed8184b7SJonas Devlieghere llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
167ed8184b7SJonas Devlieghere io_redirect_or_error = ScriptInterpreterIORedirect::Create(
168ed8184b7SJonas Devlieghere options.GetEnableIO(), m_debugger, result);
169ed8184b7SJonas Devlieghere if (!io_redirect_or_error) {
170ed8184b7SJonas Devlieghere if (result)
171ed8184b7SJonas Devlieghere result->AppendErrorWithFormatv(
172ed8184b7SJonas Devlieghere "failed to redirect I/O: {0}\n",
173ed8184b7SJonas Devlieghere llvm::fmt_consume(io_redirect_or_error.takeError()));
174ed8184b7SJonas Devlieghere else
175ed8184b7SJonas Devlieghere llvm::consumeError(io_redirect_or_error.takeError());
176ed8184b7SJonas Devlieghere return false;
177ed8184b7SJonas Devlieghere }
178ed8184b7SJonas Devlieghere
179ed8184b7SJonas Devlieghere ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;
180ed8184b7SJonas Devlieghere
181ed8184b7SJonas Devlieghere if (llvm::Error e =
182ed8184b7SJonas Devlieghere m_lua->ChangeIO(io_redirect.GetOutputFile()->GetStream(),
183ed8184b7SJonas Devlieghere io_redirect.GetErrorFile()->GetStream())) {
184ed8184b7SJonas Devlieghere result->AppendErrorWithFormatv("lua failed to redirect I/O: {0}\n",
185ed8184b7SJonas Devlieghere llvm::toString(std::move(e)));
186ed8184b7SJonas Devlieghere return false;
187ed8184b7SJonas Devlieghere }
188ed8184b7SJonas Devlieghere
1894164be72SJonas Devlieghere if (llvm::Error e = m_lua->Run(command)) {
19028613242SJonas Devlieghere result->AppendErrorWithFormatv(
19128613242SJonas Devlieghere "lua failed attempting to evaluate '{0}': {1}\n", command,
19228613242SJonas Devlieghere llvm::toString(std::move(e)));
19367de8962SJonas Devlieghere return false;
19467de8962SJonas Devlieghere }
195ed8184b7SJonas Devlieghere
196ed8184b7SJonas Devlieghere io_redirect.Flush();
19728613242SJonas Devlieghere return true;
19828613242SJonas Devlieghere }
19967de8962SJonas Devlieghere
ExecuteInterpreterLoop()20067de8962SJonas Devlieghere void ScriptInterpreterLua::ExecuteInterpreterLoop() {
2015c1c8443SJonas Devlieghere LLDB_SCOPED_TIMER();
20228613242SJonas Devlieghere
20328613242SJonas Devlieghere // At the moment, the only time the debugger does not have an input file
20428613242SJonas Devlieghere // handle is when this is called directly from lua, in which case it is
20528613242SJonas Devlieghere // both dangerous and unnecessary (not to mention confusing) to try to embed
20628613242SJonas Devlieghere // a running interpreter loop inside the already running lua interpreter
20728613242SJonas Devlieghere // loop, so we won't do it.
2086e3faaebSJonas Devlieghere if (!m_debugger.GetInputFile().IsValid())
20928613242SJonas Devlieghere return;
21028613242SJonas Devlieghere
2116e3faaebSJonas Devlieghere IOHandlerSP io_handler_sp(new IOHandlerLuaInterpreter(m_debugger, *this));
2126e3faaebSJonas Devlieghere m_debugger.RunIOHandlerAsync(io_handler_sp);
21367de8962SJonas Devlieghere }
21467de8962SJonas Devlieghere
LoadScriptingModule(const char * filename,const LoadScriptOptions & options,lldb_private::Status & error,StructuredData::ObjectSP * module_sp,FileSpec extra_search_dir)215572b9f46SJonas Devlieghere bool ScriptInterpreterLua::LoadScriptingModule(
216f9517353SJonas Devlieghere const char *filename, const LoadScriptOptions &options,
217f9517353SJonas Devlieghere lldb_private::Status &error, StructuredData::ObjectSP *module_sp,
218f9517353SJonas Devlieghere FileSpec extra_search_dir) {
219572b9f46SJonas Devlieghere
220572b9f46SJonas Devlieghere if (llvm::Error e = m_lua->LoadModule(filename)) {
221572b9f46SJonas Devlieghere error.SetErrorStringWithFormatv("lua failed to import '{0}': {1}\n",
222572b9f46SJonas Devlieghere filename, llvm::toString(std::move(e)));
223572b9f46SJonas Devlieghere return false;
224572b9f46SJonas Devlieghere }
225572b9f46SJonas Devlieghere return true;
226572b9f46SJonas Devlieghere }
227572b9f46SJonas Devlieghere
Initialize()22867de8962SJonas Devlieghere void ScriptInterpreterLua::Initialize() {
22967de8962SJonas Devlieghere static llvm::once_flag g_once_flag;
23067de8962SJonas Devlieghere
23167de8962SJonas Devlieghere llvm::call_once(g_once_flag, []() {
23267de8962SJonas Devlieghere PluginManager::RegisterPlugin(GetPluginNameStatic(),
23367de8962SJonas Devlieghere GetPluginDescriptionStatic(),
23467de8962SJonas Devlieghere lldb::eScriptLanguageLua, CreateInstance);
23567de8962SJonas Devlieghere });
23667de8962SJonas Devlieghere }
23767de8962SJonas Devlieghere
Terminate()23867de8962SJonas Devlieghere void ScriptInterpreterLua::Terminate() {}
23967de8962SJonas Devlieghere
EnterSession(user_id_t debugger_id)24045c971f7SJonas Devlieghere llvm::Error ScriptInterpreterLua::EnterSession(user_id_t debugger_id) {
24145c971f7SJonas Devlieghere if (m_session_is_active)
24245c971f7SJonas Devlieghere return llvm::Error::success();
24345c971f7SJonas Devlieghere
24445c971f7SJonas Devlieghere const char *fmt_str =
24545c971f7SJonas Devlieghere "lldb.debugger = lldb.SBDebugger.FindDebuggerWithID({0}); "
24645c971f7SJonas Devlieghere "lldb.target = lldb.debugger:GetSelectedTarget(); "
24745c971f7SJonas Devlieghere "lldb.process = lldb.target:GetProcess(); "
24845c971f7SJonas Devlieghere "lldb.thread = lldb.process:GetSelectedThread(); "
24945c971f7SJonas Devlieghere "lldb.frame = lldb.thread:GetSelectedFrame()";
25045c971f7SJonas Devlieghere return m_lua->Run(llvm::formatv(fmt_str, debugger_id).str());
25145c971f7SJonas Devlieghere }
25245c971f7SJonas Devlieghere
LeaveSession()25345c971f7SJonas Devlieghere llvm::Error ScriptInterpreterLua::LeaveSession() {
25445c971f7SJonas Devlieghere if (!m_session_is_active)
25545c971f7SJonas Devlieghere return llvm::Error::success();
25645c971f7SJonas Devlieghere
25745c971f7SJonas Devlieghere m_session_is_active = false;
25845c971f7SJonas Devlieghere
25945c971f7SJonas Devlieghere llvm::StringRef str = "lldb.debugger = nil; "
26045c971f7SJonas Devlieghere "lldb.target = nil; "
26145c971f7SJonas Devlieghere "lldb.process = nil; "
26245c971f7SJonas Devlieghere "lldb.thread = nil; "
26345c971f7SJonas Devlieghere "lldb.frame = nil";
26445c971f7SJonas Devlieghere return m_lua->Run(str);
26545c971f7SJonas Devlieghere }
26645c971f7SJonas Devlieghere
BreakpointCallbackFunction(void * baton,StoppointCallbackContext * context,user_id_t break_id,user_id_t break_loc_id)267a0d7406aSPedro Tammela bool ScriptInterpreterLua::BreakpointCallbackFunction(
268a0d7406aSPedro Tammela void *baton, StoppointCallbackContext *context, user_id_t break_id,
269a0d7406aSPedro Tammela user_id_t break_loc_id) {
270a0d7406aSPedro Tammela assert(context);
271a0d7406aSPedro Tammela
272a0d7406aSPedro Tammela ExecutionContext exe_ctx(context->exe_ctx_ref);
273a0d7406aSPedro Tammela Target *target = exe_ctx.GetTargetPtr();
274a0d7406aSPedro Tammela if (target == nullptr)
275a0d7406aSPedro Tammela return true;
276a0d7406aSPedro Tammela
277a0d7406aSPedro Tammela StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP());
278a0d7406aSPedro Tammela BreakpointSP breakpoint_sp = target->GetBreakpointByID(break_id);
279a0d7406aSPedro Tammela BreakpointLocationSP bp_loc_sp(breakpoint_sp->FindLocationByID(break_loc_id));
280a0d7406aSPedro Tammela
281a0d7406aSPedro Tammela Debugger &debugger = target->GetDebugger();
282a0d7406aSPedro Tammela ScriptInterpreterLua *lua_interpreter = static_cast<ScriptInterpreterLua *>(
283a0d7406aSPedro Tammela debugger.GetScriptInterpreter(true, eScriptLanguageLua));
284a0d7406aSPedro Tammela Lua &lua = lua_interpreter->GetLua();
285a0d7406aSPedro Tammela
286532e4203SPedro Tammela CommandDataLua *bp_option_data = static_cast<CommandDataLua *>(baton);
287532e4203SPedro Tammela llvm::Expected<bool> BoolOrErr = lua.CallBreakpointCallback(
288532e4203SPedro Tammela baton, stop_frame_sp, bp_loc_sp, bp_option_data->m_extra_args_sp);
289a0d7406aSPedro Tammela if (llvm::Error E = BoolOrErr.takeError()) {
290a0d7406aSPedro Tammela debugger.GetErrorStream() << toString(std::move(E));
291a0d7406aSPedro Tammela return true;
292a0d7406aSPedro Tammela }
293a0d7406aSPedro Tammela
294a0d7406aSPedro Tammela return *BoolOrErr;
295a0d7406aSPedro Tammela }
296a0d7406aSPedro Tammela
WatchpointCallbackFunction(void * baton,StoppointCallbackContext * context,user_id_t watch_id)297e81ba283SSiger Yang bool ScriptInterpreterLua::WatchpointCallbackFunction(
298e81ba283SSiger Yang void *baton, StoppointCallbackContext *context, user_id_t watch_id) {
299e81ba283SSiger Yang assert(context);
300e81ba283SSiger Yang
301e81ba283SSiger Yang ExecutionContext exe_ctx(context->exe_ctx_ref);
302e81ba283SSiger Yang Target *target = exe_ctx.GetTargetPtr();
303e81ba283SSiger Yang if (target == nullptr)
304e81ba283SSiger Yang return true;
305e81ba283SSiger Yang
306e81ba283SSiger Yang StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP());
307e81ba283SSiger Yang WatchpointSP wp_sp = target->GetWatchpointList().FindByID(watch_id);
308e81ba283SSiger Yang
309e81ba283SSiger Yang Debugger &debugger = target->GetDebugger();
310e81ba283SSiger Yang ScriptInterpreterLua *lua_interpreter = static_cast<ScriptInterpreterLua *>(
311e81ba283SSiger Yang debugger.GetScriptInterpreter(true, eScriptLanguageLua));
312e81ba283SSiger Yang Lua &lua = lua_interpreter->GetLua();
313e81ba283SSiger Yang
314e81ba283SSiger Yang llvm::Expected<bool> BoolOrErr =
315e81ba283SSiger Yang lua.CallWatchpointCallback(baton, stop_frame_sp, wp_sp);
316e81ba283SSiger Yang if (llvm::Error E = BoolOrErr.takeError()) {
317e81ba283SSiger Yang debugger.GetErrorStream() << toString(std::move(E));
318e81ba283SSiger Yang return true;
319e81ba283SSiger Yang }
320e81ba283SSiger Yang
321e81ba283SSiger Yang return *BoolOrErr;
322e81ba283SSiger Yang }
323e81ba283SSiger Yang
CollectDataForBreakpointCommandCallback(std::vector<std::reference_wrapper<BreakpointOptions>> & bp_options_vec,CommandReturnObject & result)324d853bd7aSPedro Tammela void ScriptInterpreterLua::CollectDataForBreakpointCommandCallback(
325cfb96d84SJim Ingham std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
326d853bd7aSPedro Tammela CommandReturnObject &result) {
327d853bd7aSPedro Tammela IOHandlerSP io_handler_sp(
328d853bd7aSPedro Tammela new IOHandlerLuaInterpreter(m_debugger, *this, eIOHandlerBreakpoint));
329d853bd7aSPedro Tammela io_handler_sp->SetUserData(&bp_options_vec);
330d853bd7aSPedro Tammela m_debugger.RunIOHandlerAsync(io_handler_sp);
331d853bd7aSPedro Tammela }
332d853bd7aSPedro Tammela
CollectDataForWatchpointCommandCallback(WatchpointOptions * wp_options,CommandReturnObject & result)333e81ba283SSiger Yang void ScriptInterpreterLua::CollectDataForWatchpointCommandCallback(
334e81ba283SSiger Yang WatchpointOptions *wp_options, CommandReturnObject &result) {
335e81ba283SSiger Yang IOHandlerSP io_handler_sp(
336e81ba283SSiger Yang new IOHandlerLuaInterpreter(m_debugger, *this, eIOHandlerWatchpoint));
337e81ba283SSiger Yang io_handler_sp->SetUserData(wp_options);
338e81ba283SSiger Yang m_debugger.RunIOHandlerAsync(io_handler_sp);
339e81ba283SSiger Yang }
340e81ba283SSiger Yang
SetBreakpointCommandCallbackFunction(BreakpointOptions & bp_options,const char * function_name,StructuredData::ObjectSP extra_args_sp)341532e4203SPedro Tammela Status ScriptInterpreterLua::SetBreakpointCommandCallbackFunction(
342cfb96d84SJim Ingham BreakpointOptions &bp_options, const char *function_name,
343532e4203SPedro Tammela StructuredData::ObjectSP extra_args_sp) {
344532e4203SPedro Tammela const char *fmt_str = "return {0}(frame, bp_loc, ...)";
345532e4203SPedro Tammela std::string oneliner = llvm::formatv(fmt_str, function_name).str();
346532e4203SPedro Tammela return RegisterBreakpointCallback(bp_options, oneliner.c_str(),
347532e4203SPedro Tammela extra_args_sp);
348532e4203SPedro Tammela }
349532e4203SPedro Tammela
SetBreakpointCommandCallback(BreakpointOptions & bp_options,const char * command_body_text)350a0d7406aSPedro Tammela Status ScriptInterpreterLua::SetBreakpointCommandCallback(
351cfb96d84SJim Ingham BreakpointOptions &bp_options, const char *command_body_text) {
352532e4203SPedro Tammela return RegisterBreakpointCallback(bp_options, command_body_text, {});
353532e4203SPedro Tammela }
354532e4203SPedro Tammela
RegisterBreakpointCallback(BreakpointOptions & bp_options,const char * command_body_text,StructuredData::ObjectSP extra_args_sp)355532e4203SPedro Tammela Status ScriptInterpreterLua::RegisterBreakpointCallback(
356cfb96d84SJim Ingham BreakpointOptions &bp_options, const char *command_body_text,
357532e4203SPedro Tammela StructuredData::ObjectSP extra_args_sp) {
358a0d7406aSPedro Tammela Status error;
359532e4203SPedro Tammela auto data_up = std::make_unique<CommandDataLua>(extra_args_sp);
360a0d7406aSPedro Tammela error = m_lua->RegisterBreakpointCallback(data_up.get(), command_body_text);
361a0d7406aSPedro Tammela if (error.Fail())
362a0d7406aSPedro Tammela return error;
363a0d7406aSPedro Tammela auto baton_sp =
364a0d7406aSPedro Tammela std::make_shared<BreakpointOptions::CommandBaton>(std::move(data_up));
365cfb96d84SJim Ingham bp_options.SetCallback(ScriptInterpreterLua::BreakpointCallbackFunction,
366a0d7406aSPedro Tammela baton_sp);
367a0d7406aSPedro Tammela return error;
368a0d7406aSPedro Tammela }
369a0d7406aSPedro Tammela
SetWatchpointCommandCallback(WatchpointOptions * wp_options,const char * command_body_text)370e81ba283SSiger Yang void ScriptInterpreterLua::SetWatchpointCommandCallback(
371e81ba283SSiger Yang WatchpointOptions *wp_options, const char *command_body_text) {
372e81ba283SSiger Yang RegisterWatchpointCallback(wp_options, command_body_text, {});
373e81ba283SSiger Yang }
374e81ba283SSiger Yang
RegisterWatchpointCallback(WatchpointOptions * wp_options,const char * command_body_text,StructuredData::ObjectSP extra_args_sp)375e81ba283SSiger Yang Status ScriptInterpreterLua::RegisterWatchpointCallback(
376e81ba283SSiger Yang WatchpointOptions *wp_options, const char *command_body_text,
377e81ba283SSiger Yang StructuredData::ObjectSP extra_args_sp) {
378e81ba283SSiger Yang Status error;
379e81ba283SSiger Yang auto data_up = std::make_unique<WatchpointOptions::CommandData>();
380e81ba283SSiger Yang error = m_lua->RegisterWatchpointCallback(data_up.get(), command_body_text);
381e81ba283SSiger Yang if (error.Fail())
382e81ba283SSiger Yang return error;
383e81ba283SSiger Yang auto baton_sp =
384e81ba283SSiger Yang std::make_shared<WatchpointOptions::CommandBaton>(std::move(data_up));
385e81ba283SSiger Yang wp_options->SetCallback(ScriptInterpreterLua::WatchpointCallbackFunction,
386e81ba283SSiger Yang baton_sp);
387e81ba283SSiger Yang return error;
388e81ba283SSiger Yang }
389e81ba283SSiger Yang
39067de8962SJonas Devlieghere lldb::ScriptInterpreterSP
CreateInstance(Debugger & debugger)39167de8962SJonas Devlieghere ScriptInterpreterLua::CreateInstance(Debugger &debugger) {
39267de8962SJonas Devlieghere return std::make_shared<ScriptInterpreterLua>(debugger);
39367de8962SJonas Devlieghere }
39467de8962SJonas Devlieghere
GetPluginDescriptionStatic()3955f4980f0SPavel Labath llvm::StringRef ScriptInterpreterLua::GetPluginDescriptionStatic() {
39667de8962SJonas Devlieghere return "Lua script interpreter";
39767de8962SJonas Devlieghere }
39867de8962SJonas Devlieghere
GetLua()3994164be72SJonas Devlieghere Lua &ScriptInterpreterLua::GetLua() { return *m_lua; }
400