[lldb/Lua] Make lldb.debugger et al available to Lua

The Python script interpreter makes the current debugger, target,
process, thread and frame available to interactive scripting sessions
through convenience variables. This patch does the same for Lua.

Differential revision: https://reviews.llvm.org/D71801
This commit is contained in:
Jonas Devlieghere
2020-01-09 08:15:01 -08:00
parent 93a1e9c90c
commit 45c971f7ee
10 changed files with 89 additions and 3 deletions

View File

@@ -10,9 +10,9 @@
#include "llvm/Support/FormatVariadic.h"
using namespace lldb_private;
using namespace lldb;
llvm::Error Lua::Run(llvm::StringRef buffer) {
std::lock_guard<std::mutex> lock(m_mutex);
int error =
luaL_loadbuffer(m_lua_state, buffer.data(), buffer.size(), "buffer") ||
lua_pcall(m_lua_state, 0, 0, 0);

View File

@@ -9,6 +9,7 @@
#ifndef liblldb_Lua_h_
#define liblldb_Lua_h_
#include "lldb/lldb-types.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
@@ -38,7 +39,6 @@ public:
llvm::Error Run(llvm::StringRef buffer);
private:
std::mutex m_mutex;
lua_State *m_lua_state;
};

View File

@@ -27,7 +27,13 @@ public:
: IOHandlerEditline(debugger, IOHandler::Type::LuaInterpreter, "lua",
">>> ", "..> ", true, debugger.GetUseColor(), 0,
*this, nullptr),
m_script_interpreter(script_interpreter) {}
m_script_interpreter(script_interpreter) {
llvm::cantFail(m_script_interpreter.EnterSession(debugger.GetID()));
}
~IOHandlerLuaInterpreter() {
llvm::cantFail(m_script_interpreter.LeaveSession());
}
void IOHandlerInputComplete(IOHandler &io_handler,
std::string &data) override {
@@ -89,6 +95,33 @@ void ScriptInterpreterLua::Initialize() {
void ScriptInterpreterLua::Terminate() {}
llvm::Error ScriptInterpreterLua::EnterSession(user_id_t debugger_id) {
if (m_session_is_active)
return llvm::Error::success();
const char *fmt_str =
"lldb.debugger = lldb.SBDebugger.FindDebuggerWithID({0}); "
"lldb.target = lldb.debugger:GetSelectedTarget(); "
"lldb.process = lldb.target:GetProcess(); "
"lldb.thread = lldb.process:GetSelectedThread(); "
"lldb.frame = lldb.thread:GetSelectedFrame()";
return m_lua->Run(llvm::formatv(fmt_str, debugger_id).str());
}
llvm::Error ScriptInterpreterLua::LeaveSession() {
if (!m_session_is_active)
return llvm::Error::success();
m_session_is_active = false;
llvm::StringRef str = "lldb.debugger = nil; "
"lldb.target = nil; "
"lldb.process = nil; "
"lldb.thread = nil; "
"lldb.frame = nil";
return m_lua->Run(str);
}
lldb::ScriptInterpreterSP
ScriptInterpreterLua::CreateInstance(Debugger &debugger) {
return std::make_shared<ScriptInterpreterLua>(debugger);

View File

@@ -43,8 +43,12 @@ public:
Lua &GetLua();
llvm::Error EnterSession(lldb::user_id_t debugger_id);
llvm::Error LeaveSession();
private:
std::unique_ptr<Lua> m_lua;
bool m_session_is_active = false;
};
} // namespace lldb_private

View File

@@ -0,0 +1,6 @@
script foobar = 40 + 7
script print(foobar)
script d = lldb.SBDebugger.Create()
script d:HandleCommand("script foobar = 40 + 2")
script print(foobar)
script d:HandleCommand("script print(foobar)")

View File

@@ -0,0 +1,6 @@
script
print(lldb.target, lldb.debugger:GetSelectedTarget())
lldb.debugger:SetSelectedTarget(lldb.debugger:GetTargetAtIndex(0))
print(lldb.target, lldb.debugger:GetSelectedTarget())
lldb.debugger:HandleCommand("script print(lldb.target, lldb.debugger:GetSelectedTarget())")
print(lldb.target, lldb.debugger:GetSelectedTarget())

View File

@@ -0,0 +1,2 @@
script
print(lldb.target, lldb.debugger:GetSelectedTarget())

View File

@@ -0,0 +1,17 @@
# REQUIRES: lua
#
# This tests that the convenience variables are not nil. Given that there is no
# target we only expect the debugger to be valid.
#
# RUN: cat %s | %lldb --script-language lua 2>&1 | FileCheck %s
script
print(string.format("lldb.debugger is valid: %s", lldb.debugger:IsValid()))
print(string.format("lldb.target is valid: %s", lldb.target:IsValid()))
print(string.format("lldb.process is valid: %s", lldb.process:IsValid()))
print(string.format("lldb.thread is valid: %s", lldb.thread:IsValid()))
print(string.format("lldb.frame is valid: %s", lldb.frame:IsValid()))
# CHECK: debugger is valid: true
# CHECK: target is valid: false
# CHECK: process is valid: false
# CHECK: thread is valid: false
# CHECK: frame is valid: false

View File

@@ -0,0 +1,6 @@
# REQUIRES: lua
#
# RUN: %lldb --script-language lua -s %S/Inputs/independent_state.in 2>&1 | FileCheck %s
# CHECK: 47
# CHECK: 47
# CHECK: 42

View File

@@ -0,0 +1,12 @@
# REQUIRES: lua
# RUN: mkdir -p %t
# RUN: echo "int main() { return 0; }" | %clang_host -x c - -o %t/foo
# RUN: echo "int main() { return 0; }" | %clang_host -x c - -o %t/bar
# RUN: %lldb --script-language lua -o "file %t/bar" -o "file %t/foo" -s %S/Inputs/nested_sessions.in -s %S/Inputs/nested_sessions_2.in 2>&1 | FileCheck %s
# CHECK: script
# CHECK-NEXT: foo foo
# CHECK-NEXT: foo bar
# CHECK-NEXT: foo bar
# CHECK-NEXT: foo bar
# CHECK: script
# CHECK-NEXT: bar bar