add 'set-breakpoint', 'remove-breakpoint' commands
This commit is contained in:
@@ -587,6 +587,7 @@ function __process_post_runnables()
|
|||||||
__vc_named_coroutines[name] = nil
|
__vc_named_coroutines[name] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
debug.pull_events()
|
||||||
network.__process_events()
|
network.__process_events()
|
||||||
block.__process_register_events()
|
block.__process_register_events()
|
||||||
block.__perform_ticks(time.delta())
|
block.__perform_ticks(time.delta())
|
||||||
|
|||||||
@@ -1,5 +1,57 @@
|
|||||||
-- Lua has no parallelizm, also _set_data does not call any lua functions so
|
-- Lua has no parallelizm, also _set_data does not call any lua functions so
|
||||||
-- may be reused one global ffi buffer per lua_State
|
-- may be reused one global ffi buffer per lua_State
|
||||||
|
|
||||||
|
local breakpoints = {}
|
||||||
|
|
||||||
|
debug.sethook(function (e, line)
|
||||||
|
local bps = breakpoints[line]
|
||||||
|
if not bps then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local source = debug.getinfo(2).source
|
||||||
|
if not bps[source] then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
debug.breakpoint()
|
||||||
|
debug.pull_events()
|
||||||
|
end, "l")
|
||||||
|
|
||||||
|
local DBG_EVENT_SET_BREAKPOINT = 1
|
||||||
|
local DBG_EVENT_RM_BREAKPOINT = 2
|
||||||
|
local __pull_events = debug.__pull_events
|
||||||
|
debug.__pull_events = nil
|
||||||
|
|
||||||
|
function debug.pull_events()
|
||||||
|
local events = __pull_events()
|
||||||
|
if not events then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
for i, event in ipairs(events) do
|
||||||
|
if event[1] == DBG_EVENT_SET_BREAKPOINT then
|
||||||
|
debug.set_breakpoint(event[2], event[3])
|
||||||
|
elseif event[1] == DBG_EVENT_RM_BREAKPOINT then
|
||||||
|
debug.remove_breakpoint(event[2], event[3])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function debug.set_breakpoint(source, line)
|
||||||
|
local bps = breakpoints[line]
|
||||||
|
if not bps then
|
||||||
|
bps = {}
|
||||||
|
breakpoints[line] = bps
|
||||||
|
end
|
||||||
|
bps[source] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
function debug.remove_breakpoint(source, line)
|
||||||
|
local bps = breakpoints[line]
|
||||||
|
if not bps then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
bps[source] = nil
|
||||||
|
end
|
||||||
|
|
||||||
local canvas_ffi_buffer
|
local canvas_ffi_buffer
|
||||||
local canvas_ffi_buffer_size = 0
|
local canvas_ffi_buffer_size = 0
|
||||||
|
|
||||||
|
|||||||
@@ -31,12 +31,14 @@ std::string ClientConnection::read() {
|
|||||||
if (length <= 0) {
|
if (length <= 0) {
|
||||||
logger.error() << "invalid message length " << length;
|
logger.error() << "invalid message length " << length;
|
||||||
} else {
|
} else {
|
||||||
|
logger.info() << "message length " << length;
|
||||||
messageLength = length;
|
messageLength = length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (connection->available() >= messageLength) {
|
} else if (connection->available() >= messageLength) {
|
||||||
std::string string(messageLength, 0);
|
std::string string(messageLength, 0);
|
||||||
connection->recv(string.data(), messageLength);
|
connection->recv(string.data(), messageLength);
|
||||||
|
messageLength = 0;
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
@@ -156,9 +158,20 @@ bool DebuggingServer::performCommand(
|
|||||||
engine.quit();
|
engine.quit();
|
||||||
connection->sendResponse("success");
|
connection->sendResponse("success");
|
||||||
} else if (type == "detach") {
|
} else if (type == "detach") {
|
||||||
|
logger.info() << "detach received";
|
||||||
connection->sendResponse("success");
|
connection->sendResponse("success");
|
||||||
connection.reset();
|
connection.reset();
|
||||||
return false;
|
return false;
|
||||||
|
} else if (type == "set-breakpoint" || type == "remove-breakpoint") {
|
||||||
|
if (!map.has("source") || !map.has("line"))
|
||||||
|
return true;
|
||||||
|
breakpointEvents.push_back(BreakpointEvent {
|
||||||
|
type[0] == 's'
|
||||||
|
? BreakpointEventType::SET_BREAKPOINT
|
||||||
|
: BreakpointEventType::REMOVE_BREAKPOINT,
|
||||||
|
map["source"].asString(),
|
||||||
|
static_cast<int>(map["line"].asInteger()),
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
logger.error() << "unsupported command '" << type << "'";
|
logger.error() << "unsupported command '" << type << "'";
|
||||||
}
|
}
|
||||||
@@ -166,8 +179,6 @@ bool DebuggingServer::performCommand(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DebuggingServer::onHitBreakpoint(dv::value&& stackTrace) {
|
void DebuggingServer::onHitBreakpoint(dv::value&& stackTrace) {
|
||||||
logger.info() << "hit breakpoint:\n"
|
|
||||||
<< json::stringify(stackTrace, true, " ");
|
|
||||||
if (connection == nullptr) {
|
if (connection == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -183,3 +194,7 @@ void DebuggingServer::setClient(u64id_t client) {
|
|||||||
this->connection =
|
this->connection =
|
||||||
std::make_unique<ClientConnection>(engine.getNetwork(), client);
|
std::make_unique<ClientConnection>(engine.getNetwork(), client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<BreakpointEvent> DebuggingServer::pullBreakpointEvents() {
|
||||||
|
return std::move(breakpointEvents);
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
|
|
||||||
@@ -35,6 +36,16 @@ namespace devtools {
|
|||||||
u64id_t connection;
|
u64id_t connection;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class BreakpointEventType {
|
||||||
|
SET_BREAKPOINT = 1,
|
||||||
|
REMOVE_BREAKPOINT,
|
||||||
|
};
|
||||||
|
struct BreakpointEvent {
|
||||||
|
BreakpointEventType type;
|
||||||
|
std::string source;
|
||||||
|
int line;
|
||||||
|
};
|
||||||
|
|
||||||
class DebuggingServer {
|
class DebuggingServer {
|
||||||
public:
|
public:
|
||||||
DebuggingServer(Engine& engine, const std::string& serverString);
|
DebuggingServer(Engine& engine, const std::string& serverString);
|
||||||
@@ -44,10 +55,12 @@ namespace devtools {
|
|||||||
void onHitBreakpoint(dv::value&& stackTrace);
|
void onHitBreakpoint(dv::value&& stackTrace);
|
||||||
|
|
||||||
void setClient(u64id_t client);
|
void setClient(u64id_t client);
|
||||||
|
std::vector<BreakpointEvent> pullBreakpointEvents();
|
||||||
private:
|
private:
|
||||||
Engine& engine;
|
Engine& engine;
|
||||||
network::Server& server;
|
network::Server& server;
|
||||||
std::unique_ptr<ClientConnection> connection;
|
std::unique_ptr<ClientConnection> connection;
|
||||||
|
std::vector<BreakpointEvent> breakpointEvents;
|
||||||
|
|
||||||
bool performCommand(const std::string& type, const dv::value& map);
|
bool performCommand(const std::string& type, const dv::value& map);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -318,6 +318,7 @@ void Engine::startPauseLoop() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (!isQuitSignal()) {
|
while (!isQuitSignal()) {
|
||||||
|
network->update();
|
||||||
if (!debuggingServer->update()) {
|
if (!debuggingServer->update()) {
|
||||||
debuggingServer.reset();
|
debuggingServer.reset();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -279,6 +279,33 @@ static int l_debug_breakpoint(lua::State* L) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int l_debug_pull_events(lua::State* L) {
|
||||||
|
if (auto server = engine->getDebuggingServer()) {
|
||||||
|
auto events = server->pullBreakpointEvents();
|
||||||
|
if (events.empty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
lua::createtable(L, events.size(), 0);
|
||||||
|
for (int i = 0; i < events.size(); i++) {
|
||||||
|
const auto& event = events[i];
|
||||||
|
lua::createtable(L, 3, 0);
|
||||||
|
|
||||||
|
lua::pushinteger(L, static_cast<int>(event.type));
|
||||||
|
lua::rawseti(L, 1);
|
||||||
|
|
||||||
|
lua::pushstring(L, event.source);
|
||||||
|
lua::rawseti(L, 2);
|
||||||
|
|
||||||
|
lua::pushinteger(L, event.line);
|
||||||
|
lua::rawseti(L, 3);
|
||||||
|
|
||||||
|
lua::rawseti(L, i + 1);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void initialize_libs_extends(lua::State* L) {
|
void initialize_libs_extends(lua::State* L) {
|
||||||
if (lua::getglobal(L, "debug")) {
|
if (lua::getglobal(L, "debug")) {
|
||||||
lua::pushcfunction(L, lua::wrap<l_debug_error>);
|
lua::pushcfunction(L, lua::wrap<l_debug_error>);
|
||||||
@@ -296,6 +323,9 @@ void initialize_libs_extends(lua::State* L) {
|
|||||||
lua::pushcfunction(L, lua::wrap<l_debug_breakpoint>);
|
lua::pushcfunction(L, lua::wrap<l_debug_breakpoint>);
|
||||||
lua::setfield(L, "breakpoint");
|
lua::setfield(L, "breakpoint");
|
||||||
|
|
||||||
|
lua::pushcfunction(L, lua::wrap<l_debug_pull_events>);
|
||||||
|
lua::setfield(L, "__pull_events");
|
||||||
|
|
||||||
lua::pop(L);
|
lua::pop(L);
|
||||||
}
|
}
|
||||||
if (lua::getglobal(L, "math")) {
|
if (lua::getglobal(L, "math")) {
|
||||||
|
|||||||
Reference in New Issue
Block a user