Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp
39642 views
1
//===-- Lua.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-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "Lua.h"
10
#include "SWIGLuaBridge.h"
11
#include "lldb/Host/FileSystem.h"
12
#include "lldb/Utility/FileSpec.h"
13
#include "llvm/Support/Error.h"
14
#include "llvm/Support/FormatVariadic.h"
15
16
using namespace lldb_private;
17
using namespace lldb;
18
19
static int lldb_print(lua_State *L) {
20
int n = lua_gettop(L);
21
lua_getglobal(L, "io");
22
lua_getfield(L, -1, "stdout");
23
lua_getfield(L, -1, "write");
24
for (int i = 1; i <= n; i++) {
25
lua_pushvalue(L, -1); // write()
26
lua_pushvalue(L, -3); // io.stdout
27
luaL_tolstring(L, i, nullptr);
28
lua_pushstring(L, i != n ? "\t" : "\n");
29
lua_call(L, 3, 0);
30
}
31
return 0;
32
}
33
34
Lua::Lua() : m_lua_state(luaL_newstate()) {
35
assert(m_lua_state);
36
luaL_openlibs(m_lua_state);
37
luaopen_lldb(m_lua_state);
38
lua_pushcfunction(m_lua_state, lldb_print);
39
lua_setglobal(m_lua_state, "print");
40
}
41
42
Lua::~Lua() {
43
assert(m_lua_state);
44
lua_close(m_lua_state);
45
}
46
47
llvm::Error Lua::Run(llvm::StringRef buffer) {
48
int error =
49
luaL_loadbuffer(m_lua_state, buffer.data(), buffer.size(), "buffer") ||
50
lua_pcall(m_lua_state, 0, 0, 0);
51
if (error == LUA_OK)
52
return llvm::Error::success();
53
54
llvm::Error e = llvm::make_error<llvm::StringError>(
55
llvm::formatv("{0}\n", lua_tostring(m_lua_state, -1)),
56
llvm::inconvertibleErrorCode());
57
// Pop error message from the stack.
58
lua_pop(m_lua_state, 1);
59
return e;
60
}
61
62
llvm::Error Lua::RegisterBreakpointCallback(void *baton, const char *body) {
63
lua_pushlightuserdata(m_lua_state, baton);
64
const char *fmt_str = "return function(frame, bp_loc, ...) {0} end";
65
std::string func_str = llvm::formatv(fmt_str, body).str();
66
if (luaL_dostring(m_lua_state, func_str.c_str()) != LUA_OK) {
67
llvm::Error e = llvm::make_error<llvm::StringError>(
68
llvm::formatv("{0}", lua_tostring(m_lua_state, -1)),
69
llvm::inconvertibleErrorCode());
70
// Pop error message from the stack.
71
lua_pop(m_lua_state, 2);
72
return e;
73
}
74
lua_settable(m_lua_state, LUA_REGISTRYINDEX);
75
return llvm::Error::success();
76
}
77
78
llvm::Expected<bool>
79
Lua::CallBreakpointCallback(void *baton, lldb::StackFrameSP stop_frame_sp,
80
lldb::BreakpointLocationSP bp_loc_sp,
81
StructuredData::ObjectSP extra_args_sp) {
82
83
lua_pushlightuserdata(m_lua_state, baton);
84
lua_gettable(m_lua_state, LUA_REGISTRYINDEX);
85
StructuredDataImpl extra_args_impl(std::move(extra_args_sp));
86
return lua::SWIGBridge::LLDBSwigLuaBreakpointCallbackFunction(
87
m_lua_state, stop_frame_sp, bp_loc_sp, extra_args_impl);
88
}
89
90
llvm::Error Lua::RegisterWatchpointCallback(void *baton, const char *body) {
91
lua_pushlightuserdata(m_lua_state, baton);
92
const char *fmt_str = "return function(frame, wp, ...) {0} end";
93
std::string func_str = llvm::formatv(fmt_str, body).str();
94
if (luaL_dostring(m_lua_state, func_str.c_str()) != LUA_OK) {
95
llvm::Error e = llvm::make_error<llvm::StringError>(
96
llvm::formatv("{0}", lua_tostring(m_lua_state, -1)),
97
llvm::inconvertibleErrorCode());
98
// Pop error message from the stack.
99
lua_pop(m_lua_state, 2);
100
return e;
101
}
102
lua_settable(m_lua_state, LUA_REGISTRYINDEX);
103
return llvm::Error::success();
104
}
105
106
llvm::Expected<bool>
107
Lua::CallWatchpointCallback(void *baton, lldb::StackFrameSP stop_frame_sp,
108
lldb::WatchpointSP wp_sp) {
109
110
lua_pushlightuserdata(m_lua_state, baton);
111
lua_gettable(m_lua_state, LUA_REGISTRYINDEX);
112
return lua::SWIGBridge::LLDBSwigLuaWatchpointCallbackFunction(
113
m_lua_state, stop_frame_sp, wp_sp);
114
}
115
116
llvm::Error Lua::CheckSyntax(llvm::StringRef buffer) {
117
int error =
118
luaL_loadbuffer(m_lua_state, buffer.data(), buffer.size(), "buffer");
119
if (error == LUA_OK) {
120
// Pop buffer
121
lua_pop(m_lua_state, 1);
122
return llvm::Error::success();
123
}
124
125
llvm::Error e = llvm::make_error<llvm::StringError>(
126
llvm::formatv("{0}\n", lua_tostring(m_lua_state, -1)),
127
llvm::inconvertibleErrorCode());
128
// Pop error message from the stack.
129
lua_pop(m_lua_state, 1);
130
return e;
131
}
132
133
llvm::Error Lua::LoadModule(llvm::StringRef filename) {
134
const FileSpec file(filename);
135
if (!FileSystem::Instance().Exists(file)) {
136
return llvm::make_error<llvm::StringError>("invalid path",
137
llvm::inconvertibleErrorCode());
138
}
139
140
if (file.GetFileNameExtension() != ".lua") {
141
return llvm::make_error<llvm::StringError>("invalid extension",
142
llvm::inconvertibleErrorCode());
143
}
144
145
int error = luaL_loadfile(m_lua_state, filename.data()) ||
146
lua_pcall(m_lua_state, 0, 1, 0);
147
if (error != LUA_OK) {
148
llvm::Error e = llvm::make_error<llvm::StringError>(
149
llvm::formatv("{0}\n", lua_tostring(m_lua_state, -1)),
150
llvm::inconvertibleErrorCode());
151
// Pop error message from the stack.
152
lua_pop(m_lua_state, 1);
153
return e;
154
}
155
156
ConstString module_name = file.GetFileNameStrippingExtension();
157
lua_setglobal(m_lua_state, module_name.GetCString());
158
return llvm::Error::success();
159
}
160
161
llvm::Error Lua::ChangeIO(FILE *out, FILE *err) {
162
assert(out != nullptr);
163
assert(err != nullptr);
164
165
lua_getglobal(m_lua_state, "io");
166
167
lua_getfield(m_lua_state, -1, "stdout");
168
if (luaL_Stream *s = static_cast<luaL_Stream *>(
169
luaL_testudata(m_lua_state, -1, LUA_FILEHANDLE))) {
170
s->f = out;
171
lua_pop(m_lua_state, 1);
172
} else {
173
lua_pop(m_lua_state, 2);
174
return llvm::make_error<llvm::StringError>("could not get stdout",
175
llvm::inconvertibleErrorCode());
176
}
177
178
lua_getfield(m_lua_state, -1, "stderr");
179
if (luaL_Stream *s = static_cast<luaL_Stream *>(
180
luaL_testudata(m_lua_state, -1, LUA_FILEHANDLE))) {
181
s->f = out;
182
lua_pop(m_lua_state, 1);
183
} else {
184
lua_pop(m_lua_state, 2);
185
return llvm::make_error<llvm::StringError>("could not get stderr",
186
llvm::inconvertibleErrorCode());
187
}
188
189
lua_pop(m_lua_state, 1);
190
return llvm::Error::success();
191
}
192
193