In order to run a {break,watch}point command, lldb can resolve to the
script interpreter to run an arbitrary piece of code or call into a
user-provided function. To do so, we will generate a wrapping function,
where we first copy lldb's internal dictionary keys into the
interpreter's global dictionary, copied inline the user code before
resetting the global dictionary to its previous state.
However, {break,watch}point commands can optionally return a value that
would tell lldb whether we should stop or not. This feature was
only implemented for breakpoint commands and since we inlined the user
code directly into the wrapping function, introducing an early return,
that caused lldb to let the interpreter global dictionary tinted with the
internal dictionary keys.
This patch fixes that issue while also adding the stopping behaviour to
watchpoint commands.
To do so, this patch refactors the {break,watch}point command creation
method, to let the lldb wrapper function generator know if the user code is
a function call or a arbitrary expression.
Then the wrapper generator, if the user input was a function call, the
wrapper function will call the user function and save the return value into
a variable. If the user input was an arbitrary expression, the wrapper will
inline it into a nested function, call the nested function and save the
return value into the same variable. After resetting the interpreter global
dictionary to its previous state, the generated wrapper function will return
the varible containing the return value.
rdar://105461140
Differential Revision: https://reviews.llvm.org/D144688
Signed-off-by: Med Ismail Bennani <medismail.bennani@gmail.com>
117 lines
4.2 KiB
C++
117 lines
4.2 KiB
C++
//===-- ScriptInterpreterLua.h ----------------------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef liblldb_ScriptInterpreterLua_h_
|
|
#define liblldb_ScriptInterpreterLua_h_
|
|
|
|
#include <vector>
|
|
|
|
#include "lldb/Breakpoint/WatchpointOptions.h"
|
|
#include "lldb/Core/StructuredDataImpl.h"
|
|
#include "lldb/Interpreter/ScriptInterpreter.h"
|
|
#include "lldb/Utility/Status.h"
|
|
#include "lldb/lldb-enumerations.h"
|
|
|
|
namespace lldb_private {
|
|
class Lua;
|
|
class ScriptInterpreterLua : public ScriptInterpreter {
|
|
public:
|
|
class CommandDataLua : public BreakpointOptions::CommandData {
|
|
public:
|
|
CommandDataLua() : BreakpointOptions::CommandData() {
|
|
interpreter = lldb::eScriptLanguageLua;
|
|
}
|
|
CommandDataLua(StructuredData::ObjectSP extra_args_sp)
|
|
: BreakpointOptions::CommandData(), m_extra_args_sp(extra_args_sp) {
|
|
interpreter = lldb::eScriptLanguageLua;
|
|
}
|
|
StructuredData::ObjectSP m_extra_args_sp;
|
|
};
|
|
|
|
ScriptInterpreterLua(Debugger &debugger);
|
|
|
|
~ScriptInterpreterLua() override;
|
|
|
|
bool ExecuteOneLine(
|
|
llvm::StringRef command, CommandReturnObject *result,
|
|
const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
|
|
|
|
void ExecuteInterpreterLoop() override;
|
|
|
|
bool LoadScriptingModule(const char *filename,
|
|
const LoadScriptOptions &options,
|
|
lldb_private::Status &error,
|
|
StructuredData::ObjectSP *module_sp = nullptr,
|
|
FileSpec extra_search_dir = {}) override;
|
|
|
|
StructuredData::DictionarySP GetInterpreterInfo() override;
|
|
|
|
// Static Functions
|
|
static void Initialize();
|
|
|
|
static void Terminate();
|
|
|
|
static lldb::ScriptInterpreterSP CreateInstance(Debugger &debugger);
|
|
|
|
static llvm::StringRef GetPluginNameStatic() { return "script-lua"; }
|
|
|
|
static llvm::StringRef GetPluginDescriptionStatic();
|
|
|
|
static bool BreakpointCallbackFunction(void *baton,
|
|
StoppointCallbackContext *context,
|
|
lldb::user_id_t break_id,
|
|
lldb::user_id_t break_loc_id);
|
|
|
|
static bool WatchpointCallbackFunction(void *baton,
|
|
StoppointCallbackContext *context,
|
|
lldb::user_id_t watch_id);
|
|
|
|
// PluginInterface protocol
|
|
llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
|
|
|
|
Lua &GetLua();
|
|
|
|
llvm::Error EnterSession(lldb::user_id_t debugger_id);
|
|
llvm::Error LeaveSession();
|
|
|
|
void CollectDataForBreakpointCommandCallback(
|
|
std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
|
|
CommandReturnObject &result) override;
|
|
|
|
void
|
|
CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options,
|
|
CommandReturnObject &result) override;
|
|
|
|
Status SetBreakpointCommandCallback(BreakpointOptions &bp_options,
|
|
const char *command_body_text,
|
|
const bool is_callback) override;
|
|
|
|
void SetWatchpointCommandCallback(WatchpointOptions *wp_options,
|
|
const char *command_body_text) override;
|
|
|
|
Status SetBreakpointCommandCallbackFunction(
|
|
BreakpointOptions &bp_options, const char *function_name,
|
|
StructuredData::ObjectSP extra_args_sp) override;
|
|
|
|
private:
|
|
std::unique_ptr<Lua> m_lua;
|
|
bool m_session_is_active = false;
|
|
|
|
Status RegisterBreakpointCallback(BreakpointOptions &bp_options,
|
|
const char *command_body_text,
|
|
StructuredData::ObjectSP extra_args_sp);
|
|
|
|
Status RegisterWatchpointCallback(WatchpointOptions *wp_options,
|
|
const char *command_body_text,
|
|
StructuredData::ObjectSP extra_args_sp);
|
|
};
|
|
|
|
} // namespace lldb_private
|
|
|
|
#endif // liblldb_ScriptInterpreterLua_h_
|