diff --git a/sourcepawn/jit/AMBuilder b/sourcepawn/jit/AMBuilder index 88ba7434..ec77f382 100644 --- a/sourcepawn/jit/AMBuilder +++ b/sourcepawn/jit/AMBuilder @@ -18,7 +18,10 @@ def setup(binary): compiler = binary.compiler compiler.includes += Includes if compiler.vendor == 'gcc' or compiler.vendor == 'clang': - compiler.cxxflags += ['-fno-rtti'] + compiler.cxxflags += [ + '-fno-rtti', + '-Wno-invalid-offsetof', + ] elif binary.compiler.vendor == 'msvc': compiler.cxxflags += ['/GR-'] diff --git a/sourcepawn/jit/debug-trace.cpp b/sourcepawn/jit/debug-trace.cpp index c3a3e60d..569d3291 100644 --- a/sourcepawn/jit/debug-trace.cpp +++ b/sourcepawn/jit/debug-trace.cpp @@ -20,6 +20,7 @@ using namespace SourcePawn; CContextTrace::CContextTrace(PluginRuntime *pRuntime, int err, const char *errstr, cell_t start_rp) : m_pRuntime(pRuntime), + context_(pRuntime->GetBaseContext()), m_Error(err), m_pMsg(errstr), m_StartRp(start_rp), @@ -66,20 +67,18 @@ CContextTrace::GetTraceInfo(CallStackInfo *trace) if (m_Level == 0) { cip = m_ctx->cip; - } else if (m_ctx->rp > 0) { + } else if (context_->rp() > 0) { /* Entries go from ctx.rp - 1 to m_StartRp */ cell_t offs, start, end; offs = m_Level - 1; - start = m_ctx->rp - 1; + start = context_->rp() - 1; end = m_StartRp; if (start - offs < end) - { return false; - } - cip = m_ctx->rstk_cips[start - offs]; + cip = context_->getReturnStackCip(start - offs); } else { return false; } diff --git a/sourcepawn/jit/debug-trace.h b/sourcepawn/jit/debug-trace.h index e6d3f3f2..acecae2c 100644 --- a/sourcepawn/jit/debug-trace.h +++ b/sourcepawn/jit/debug-trace.h @@ -16,6 +16,7 @@ #include class PluginRuntime; +class PluginContext; namespace sp { @@ -37,6 +38,7 @@ class CContextTrace : public IContextTrace private: PluginRuntime *m_pRuntime; + PluginContext *context_; sp_context_t *m_ctx; int m_Error; const char *m_pMsg; diff --git a/sourcepawn/jit/interpreter.cpp b/sourcepawn/jit/interpreter.cpp index 1cc394cd..adcfb47f 100644 --- a/sourcepawn/jit/interpreter.cpp +++ b/sourcepawn/jit/interpreter.cpp @@ -236,7 +236,8 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) if (!IsValidOffset(aCodeStart) || aCodeStart > plugin->pcode_size) return SP_ERROR_INVALID_INSTRUCTION; - sp_context_t *ctx = rt->GetBaseContext()->GetCtx(); + PluginContext *cx = rt->GetBaseContext(); + sp_context_t *ctx = cx->GetCtx(); ctx->err = SP_ERROR_NONE; // Save the original frm. BaseContext won't, and if we error, we won't hit @@ -889,14 +890,12 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) goto error; } - if (ctx->rp >= SP_MAX_RETURN_STACK) { + // For debugging. + uintptr_t rcip = uintptr_t(cip - 2) - uintptr_t(plugin->pcode); + if (!cx->pushReturnCip(rcip)) { ctx->err = SP_ERROR_STACKLOW; goto error; } - - // For debugging. - uintptr_t rcip = uintptr_t(cip - 2) - uintptr_t(plugin->pcode); - ctx->rstk_cips[ctx->rp++] = rcip; ctx->cip = offset; ctx->sp = uintptr_t(stk) - uintptr_t(plugin->memory); @@ -904,7 +903,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) stk = reinterpret_cast(plugin->memory + ctx->sp); ctx->cip = rcip; - ctx->rp--; + cx->popReturnCip(); if (err != SP_ERROR_NONE) goto error; diff --git a/sourcepawn/jit/jit_shared.h b/sourcepawn/jit/jit_shared.h index 8c615bf4..7cdb176a 100644 --- a/sourcepawn/jit/jit_shared.h +++ b/sourcepawn/jit/jit_shared.h @@ -85,8 +85,6 @@ typedef struct sp_context_s sp_plugin_t *plugin; PluginContext *basecx; void * vm[8]; /**< VM-specific pointers */ - cell_t rp; /**< Return stack pointer */ - cell_t rstk_cips[SP_MAX_RETURN_STACK]; } sp_context_t; //#define SPFLAG_PLUGIN_DEBUG (1<<0) diff --git a/sourcepawn/jit/plugin-context.cpp b/sourcepawn/jit/plugin-context.cpp index 79d0e451..f444826c 100644 --- a/sourcepawn/jit/plugin-context.cpp +++ b/sourcepawn/jit/plugin-context.cpp @@ -56,7 +56,7 @@ PluginContext::PluginContext(PluginRuntime *pRuntime) m_ctx.frm = m_ctx.sp; m_ctx.n_err = SP_ERROR_NONE; m_ctx.n_idx = SP_ERROR_NONE; - m_ctx.rp = 0; + rp_ = 0; m_ctx.tracker = new tracker_t; m_ctx.tracker->pBase = (ucell_t *)malloc(1024); @@ -584,7 +584,7 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne save_hp = m_ctx.hp; save_exec = m_InExec; save_n_idx = m_ctx.n_idx; - save_rp = m_ctx.rp; + save_rp = rp_; save_cip = m_ctx.cip; /* Push parameters */ @@ -628,10 +628,10 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne m_ctx.hp, save_hp); } - if (m_ctx.rp != save_rp) { + if (rp_ != save_rp) { ir = SP_ERROR_STACKLEAK; _SetErrorMessage("Return stack leak detected: rp:%d should be %d!", - m_ctx.rp, + rp_, save_rp); } } @@ -644,7 +644,7 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne m_ctx.sp = save_sp; m_ctx.hp = save_hp; - m_ctx.rp = save_rp; + rp_ = save_rp; m_ctx.cip = save_cip; m_ctx.n_idx = save_n_idx; diff --git a/sourcepawn/jit/plugin-context.h b/sourcepawn/jit/plugin-context.h index a96da4a2..b853a247 100644 --- a/sourcepawn/jit/plugin-context.h +++ b/sourcepawn/jit/plugin-context.h @@ -76,6 +76,31 @@ class PluginContext : public IPluginContext public: bool IsInExec(); + static inline size_t offsetOfRp() { + return offsetof(PluginContext, rp_); + } + static inline size_t offsetOfRstkCips() { + return offsetof(PluginContext, rstk_cips_); + } + + bool pushReturnCip(cell_t cip) { + if (rp_ >= SP_MAX_RETURN_STACK) + return false; + rstk_cips_[rp_++] = cip; + return true; + } + void popReturnCip() { + assert(rp_ > 0); + rp_--; + } + cell_t rp() const { + return rp_; + } + cell_t getReturnStackCip(int index) { + assert(index >= 0 && index < SP_MAX_RETURN_STACK); + return rstk_cips_[index]; + } + private: void SetErrorMessage(const char *msg, va_list ap); void _SetErrorMessage(const char *msg, ...); @@ -90,6 +115,10 @@ class PluginContext : public IPluginContext sp_context_t m_ctx; void *m_keys[4]; bool m_keys_set[4]; + + // Return stack. + cell_t rp_; + cell_t rstk_cips_[SP_MAX_RETURN_STACK]; }; #endif //_INCLUDE_SOURCEPAWN_BASECONTEXT_H_ diff --git a/sourcepawn/jit/x86/jit_x86.cpp b/sourcepawn/jit/x86/jit_x86.cpp index 5c00bcac..1422b88a 100644 --- a/sourcepawn/jit/x86/jit_x86.cpp +++ b/sourcepawn/jit/x86/jit_x86.cpp @@ -1462,8 +1462,8 @@ Compiler::emitCall() // eax = context // ecx = rp - __ movl(eax, intptr_t(rt_->GetBaseContext()->GetCtx())); - __ movl(ecx, Operand(eax, offsetof(sp_context_t, rp))); + __ movl(eax, intptr_t(rt_->GetBaseContext())); + __ movl(ecx, Operand(eax, PluginContext::offsetOfRp())); // Check if the return stack is used up. __ cmpl(ecx, SP_MAX_RETURN_STACK); @@ -1471,10 +1471,10 @@ Compiler::emitCall() // Add to the return stack. uintptr_t cip = uintptr_t(cip_ - 2) - uintptr_t(plugin_->pcode); - __ movl(Operand(eax, ecx, ScaleFour, offsetof(sp_context_t, rstk_cips)), cip); + __ movl(Operand(eax, ecx, ScaleFour, PluginContext::offsetOfRstkCips()), cip); // Increment the return stack pointer. - __ addl(Operand(eax, offsetof(sp_context_t, rp)), 1); + __ addl(Operand(eax, PluginContext::offsetOfRp()), 1); // Store the CIP of the function we're about to call. __ movl(Operand(cipAddr()), offset); @@ -1495,8 +1495,8 @@ Compiler::emitCall() __ movl(Operand(cipAddr()), cip); // Mark us as leaving the last frame. - __ movl(tmp, intptr_t(rt_->GetBaseContext()->GetCtx())); - __ subl(Operand(tmp, offsetof(sp_context_t, rp)), 1); + __ movl(tmp, intptr_t(rt_->GetBaseContext())); + __ subl(Operand(tmp, PluginContext::offsetOfRp()), 1); return true; }