diff --git a/sourcepawn/jit/engine2.cpp b/sourcepawn/jit/engine2.cpp index 09023cbd..62a5294b 100644 --- a/sourcepawn/jit/engine2.cpp +++ b/sourcepawn/jit/engine2.cpp @@ -1,5 +1,6 @@ // vim: set ts=4 sw=4 tw=99 noet: #include +#include #include #include #include "engine2.h" @@ -220,3 +221,15 @@ bool SourcePawnEngine2::InstallWatchdogTimer(size_t timeout_ms) return g_WatchdogTimer.Initialize(timeout_ms); } +void LogFatalPCodeError(const char *fmt, ...) +{ + FILE *fp = fopen("spjit-fatal-log.txt", "at"); + if (!fp) + return; + va_list ap; + va_start(ap, fmt); + vfprintf(fp, fmt, ap); + fprintf(fp, "\n"); + va_end(ap); + fclose(fp); +} diff --git a/sourcepawn/jit/engine2.h b/sourcepawn/jit/engine2.h index e9cb980e..be0bdfe7 100644 --- a/sourcepawn/jit/engine2.h +++ b/sourcepawn/jit/engine2.h @@ -45,6 +45,8 @@ namespace SourcePawn }; } +extern void LogFatalPCodeError(const char *fmt, ...); + extern SourcePawn::SourcePawnEngine2 g_engine2; #endif //_INCLUDE_SOURCEPAWN_ENGINE_2_H_ diff --git a/sourcepawn/jit/interpreter.cpp b/sourcepawn/jit/interpreter.cpp index 257e9414..89fca60a 100644 --- a/sourcepawn/jit/interpreter.cpp +++ b/sourcepawn/jit/interpreter.cpp @@ -19,6 +19,7 @@ #include "interpreter.h" #include "opcodes.h" #include "watchdog_timer.h" +#include "engine2.h" #define STACK_MARGIN 64 @@ -46,6 +47,10 @@ static inline cell_t * Jump(const sp_plugin_t *plugin, sp_context_t *ctx, cell_t target) { if (!IsValidOffset(target) || uint32_t(target) >= plugin->pcode_size) { + LogFatalPCodeError("[i] invalid jump (name=%s) (target=%d)", + plugin->name, + target + ); ctx->err = SP_ERROR_INVALID_INSTRUCTION; return NULL; } @@ -61,6 +66,11 @@ JumpTarget(const sp_plugin_t *plugin, sp_context_t *ctx, cell_t *cip, bool cond) cell_t target = *cip; if (!IsValidOffset(target) || uint32_t(target) >= plugin->pcode_size) { + LogFatalPCodeError("[i] invalid jump (name=%s) (cip=%d) (target=%d)", + plugin->name, + cell_t((uint8_t *)cip - plugin->pcode), + target + ); ctx->err = SP_ERROR_INVALID_INSTRUCTION; return NULL; } @@ -231,8 +241,14 @@ Interpret(BaseRuntime *rt, uint32_t aCodeStart, cell_t *rval) cell_t *code = reinterpret_cast(plugin->pcode); cell_t *codeend = reinterpret_cast(plugin->pcode + plugin->pcode_size); - if (!IsValidOffset(aCodeStart) || aCodeStart > plugin->pcode_size) + if (!IsValidOffset(aCodeStart) || aCodeStart > plugin->pcode_size) { + LogFatalPCodeError("[i] invalid cs (name=%s) (cs=%d) (size=%d)", + rt->plugin()->name, + aCodeStart, + plugin->pcode_size + ); return SP_ERROR_INVALID_INSTRUCTION; + } sp_context_t *ctx = rt->GetBaseContext()->GetCtx(); ctx->err = SP_ERROR_NONE; @@ -248,6 +264,11 @@ Interpret(BaseRuntime *rt, uint32_t aCodeStart, cell_t *rval) for (;;) { if (cip >= codeend) { + LogFatalPCodeError("[i] cip overrun (name=%s) (cs=%d) (cip=%d)", + rt->plugin()->name, + aCodeStart, + cell_t(cip - code) + ); ctx->err = SP_ERROR_INVALID_INSTRUCTION; goto error; } @@ -764,6 +785,11 @@ Interpret(BaseRuntime *rt, uint32_t aCodeStart, cell_t *rval) { cell_t amount = *cip++; if (!IsValidOffset(amount)) { + LogFatalPCodeError("[i] invalid stack offset (name=%s) (cs=%d) (cip=%d)", + rt->plugin()->name, + aCodeStart, + cell_t(cip - code) + ); ctx->err = SP_ERROR_INVALID_INSTRUCTION; goto error; } @@ -970,6 +996,11 @@ Interpret(BaseRuntime *rt, uint32_t aCodeStart, cell_t *rval) default: { + LogFatalPCodeError("[i] unknown instruction (name=%s) (cs=%d) (cip=%d)", + rt->plugin()->name, + aCodeStart, + cell_t(cip - code) + ); ctx->err = SP_ERROR_INVALID_INSTRUCTION; goto error; } diff --git a/sourcepawn/jit/x86/jit_x86.cpp b/sourcepawn/jit/x86/jit_x86.cpp index df68bd57..2f218930 100644 --- a/sourcepawn/jit/x86/jit_x86.cpp +++ b/sourcepawn/jit/x86/jit_x86.cpp @@ -323,6 +323,12 @@ JitFunction * Compiler::emit(int *errp) { if (cip_ >= code_end_ || *cip_ != OP_PROC) { + LogFatalPCodeError("[j] emit() overran cip (name=%s) (cs=%d) (ce=%d) (cip=%d)", + plugin_->name, + pcode_start_, + cell_t((uint8_t *)cip_ - plugin_->pcode), + cell_t((uint8_t *)code_end_ - plugin_->pcode) + ); *errp = SP_ERROR_INVALID_INSTRUCTION; return NULL; } @@ -1345,6 +1351,13 @@ Compiler::emitOp(OPCODE op) break; default: + LogFatalPCodeError("[j] unknown opcode (name=%s) (cs=%d) (ce=%d) (cip=%d) (op=%d)", + plugin_->name, + pcode_start_, + cell_t((uint8_t *)cip_ - plugin_->pcode), + cell_t((uint8_t *)code_end_ - plugin_->pcode), + op + ); error_ = SP_ERROR_INVALID_INSTRUCTION; return false; } @@ -1544,6 +1557,12 @@ cell_t Compiler::readCell() { if (cip_ >= code_end_) { + LogFatalPCodeError("[j] readCell() overran (name=%s) (cs=%d) (ce=%d) (cip=%d)", + plugin_->name, + pcode_start_, + cell_t((uint8_t *)cip_ - plugin_->pcode), + cell_t((uint8_t *)code_end_ - plugin_->pcode) + ); error_= SP_ERROR_INVALID_INSTRUCTION; return 0; }