Move the debug return stack into PluginContext.

This commit is contained in:
dvander@alliedmods.net 2015-02-24 15:20:00 -08:00
parent 8c35d79576
commit 37af05c456
8 changed files with 56 additions and 26 deletions

View File

@ -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-']

View File

@ -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;
}

View File

@ -16,6 +16,7 @@
#include <sp_vm_api.h>
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;

View File

@ -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<cell_t *>(plugin->memory + ctx->sp);
ctx->cip = rcip;
ctx->rp--;
cx->popReturnCip();
if (err != SP_ERROR_NONE)
goto error;

View File

@ -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)

View File

@ -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;

View File

@ -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_

View File

@ -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;
}