Debugger: Lua - Modify Lua core to implement watchdog timer to bypass Lua hooks and improve performance

This commit is contained in:
Sour 2022-07-31 20:27:20 -04:00
parent 4c108d9055
commit c7ebd57e06
8 changed files with 41 additions and 7 deletions

View file

@ -46,12 +46,13 @@ LuaScriptingContext::~LuaScriptingContext()
}
}
void LuaScriptingContext::ExecutionCountHook(lua_State *lua, lua_Debug *ar)
void LuaScriptingContext::ExecutionCountHook(lua_State *lua)
{
uint32_t timeout = _context->_settings->GetDebugConfig().ScriptTimeout;
if(_context->_timer.GetElapsedMS() > timeout * 1000) {
luaL_error(lua, (std::string("Maximum execution time (") + std::to_string(timeout) + " seconds) exceeded.").c_str());
}
lua_setwatchdogtimer(lua, LuaScriptingContext::ExecutionCountHook, 1000);
}
void LuaScriptingContext::LuaOpenLibs(lua_State* L, bool allowIoOsAccess)
@ -116,7 +117,7 @@ bool LuaScriptingContext::LoadScript(string scriptName, string scriptContent, De
Log("Loading script...");
if((iErr = luaL_loadbufferx(_lua, scriptContent.c_str(), scriptContent.size(), ("@" + scriptName).c_str(), nullptr)) == 0) {
_timer.Reset();
lua_sethook(_lua, LuaScriptingContext::ExecutionCountHook, LUA_MASKCOUNT, 1000);
lua_setwatchdogtimer(_lua, LuaScriptingContext::ExecutionCountHook, 1000);
if((iErr = lua_pcall(_lua, 0, LUA_MULTRET, 0)) == 0) {
//Script loaded properly
Log("Script loaded successfully.");
@ -149,15 +150,20 @@ void LuaScriptingContext::InternalCallMemoryCallback(uint32_t addr, uint8_t &val
return;
}
_timer.Reset();
_context = this;
lua_sethook(_lua, LuaScriptingContext::ExecutionCountHook, LUA_MASKCOUNT, 1000);
bool needTimerReset = true;
lua_setwatchdogtimer(_lua, LuaScriptingContext::ExecutionCountHook, 1000);
LuaApi::SetContext(this);
for(MemoryCallback &callback: _callbacks[(int)type]) {
if(callback.Type != cpuType || addr < callback.StartAddress || addr > callback.EndAddress) {
continue;
}
if(needTimerReset) {
_timer.Reset();
needTimerReset = false;
}
int top = lua_gettop(_lua);
lua_rawgeti(_lua, LUA_REGISTRYINDEX, callback.Reference);
lua_pushinteger(_lua, addr);
@ -183,7 +189,7 @@ int LuaScriptingContext::InternalCallEventCallback(EventType type)
_timer.Reset();
_context = this;
lua_sethook(_lua, LuaScriptingContext::ExecutionCountHook, LUA_MASKCOUNT, 1000);
lua_setwatchdogtimer(_lua, LuaScriptingContext::ExecutionCountHook, 1000);
LuaApi::SetContext(this);
LuaCallHelper l(_lua);
for(int &ref : _eventCallbacks[(int)type]) {

View file

@ -6,7 +6,6 @@
#include "Utilities/Timer.h"
struct lua_State;
struct lua_Debug;
class Debugger;
class EmuSettings;
@ -18,7 +17,7 @@ private:
Timer _timer;
EmuSettings* _settings = nullptr;
static void ExecutionCountHook(lua_State* lua, lua_Debug* ar);
static void ExecutionCountHook(lua_State* lua);
void LuaOpenLibs(lua_State* L, bool allowIoOsAccess);

View file

@ -772,12 +772,14 @@ static int skipcomment (LoadF *lf, int *cp) {
else return 0; /* no comment */
}
// ##### MESEN MODIFICATION #####
int SANDBOX_ALLOW_LOADFILE = 0;
LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
const char *mode) {
if (!SANDBOX_ALLOW_LOADFILE) {
return LUA_ERRERR;
}
// ##### MESEN MODIFICATION #####
LoadF lf;
int status, readstatus;

View file

@ -15,7 +15,9 @@
#include "luaconf.h"
#include "lua.h"
// ##### MESEN MODIFICATION #####
extern int SANDBOX_ALLOW_LOADFILE;
// ##### MESEN MODIFICATION #####
/* global table */
#define LUA_GNAME "_G"

View file

@ -141,6 +141,13 @@ LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
settraps(L->ci); /* to trace inside 'luaV_execute' */
}
// ##### MESEN MODIFICATION #####
LUA_API void lua_setwatchdogtimer(lua_State* L, lua_WatchDogHook func, int count)
{
L->watchdoghook = func;
L->watchdogtimer = count;
}
// ##### MESEN MODIFICATION #####
LUA_API lua_Hook lua_gethook (lua_State *L) {
return L->hook;

View file

@ -324,6 +324,11 @@ struct lua_State {
int basehookcount;
int hookcount;
volatile l_signalT hookmask;
// ##### MESEN MODIFICATION #####
int watchdogtimer;
lua_WatchDogHook watchdoghook;
// ##### MESEN MODIFICATION #####
};

View file

@ -448,6 +448,10 @@ typedef struct lua_Debug lua_Debug; /* activation record */
/* Functions to be called by the debugger in specific events */
typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
// ##### MESEN MODIFICATION #####
typedef void (*lua_WatchDogHook) (lua_State* L);
// ##### MESEN MODIFICATION #####
LUA_API int (lua_getstack) (lua_State *L, int level, lua_Debug *ar);
LUA_API int (lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar);
@ -461,6 +465,11 @@ LUA_API void (lua_upvaluejoin) (lua_State *L, int fidx1, int n1,
int fidx2, int n2);
LUA_API void (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count);
// ##### MESEN MODIFICATION #####
LUA_API void lua_setwatchdogtimer(lua_State* L, lua_WatchDogHook func, int count);
// ##### MESEN MODIFICATION #####
LUA_API lua_Hook (lua_gethook) (lua_State *L);
LUA_API int (lua_gethookmask) (lua_State *L);
LUA_API int (lua_gethookcount) (lua_State *L);

View file

@ -1122,7 +1122,11 @@ void luaV_finishOp (lua_State *L) {
/* fetch an instruction and prepare its execution */
// ##### MESEN MODIFICATION (watchdogtimer) #####
#define vmfetch() { \
if (L->watchdogtimer && !--L->watchdogtimer) { \
(*L->watchdoghook)(L); \
} \
if (l_unlikely(trap)) { /* stack reallocation or hooks? */ \
trap = luaG_traceexec(L, pc); /* handle hooks */ \
updatebase(ci); /* correct stack */ \