Permalink
Browse files

Expose stack context traces to SourcePawn.

  • Loading branch information...
VoiDeD committed Sep 25, 2014
1 parent 9eb1b3e commit a87226f5c96b87d9cf6b225aa91d48449c86a10a
View
@@ -50,6 +50,7 @@
#endif
HandleType_t g_PlIter;
HandleType_t g_ContextTrace;
IForward *g_OnLogAction = NULL;
@@ -67,6 +68,7 @@ class CoreNativeHelpers :
hacc.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY|HANDLE_RESTRICT_OWNER;
g_PlIter = handlesys->CreateType("PluginIterator", this, 0, NULL, NULL, g_pCoreIdent, NULL);
g_ContextTrace = handlesys->CreateType("SPContextTrace", this, 0, NULL, NULL, g_pCoreIdent, NULL );
g_OnLogAction = forwardsys->CreateForward("OnLogAction",
ET_Hook,
@@ -82,12 +84,20 @@ class CoreNativeHelpers :
}
void OnHandleDestroy(HandleType_t type, void *object)
{
IPluginIterator *iter = (IPluginIterator *)object;
iter->Release();
if (type == g_PlIter)
{
IPluginIterator *iter = (IPluginIterator *)object;
iter->Release();
}
else if (type == g_ContextTrace)
{
g_pSourcePawn2->FreeContextTrace((IContextTrace *)object);
}
}
void OnSourceModShutdown()
{
forwardsys->ReleaseForward(g_OnLogAction);
handlesys->RemoveType(g_ContextTrace, g_pCoreIdent);
handlesys->RemoveType(g_PlIter, g_pCoreIdent);
}
} g_CoreNativeHelpers;
@@ -745,6 +755,51 @@ static cell_t StoreToAddress(IPluginContext *pContext, const cell_t *params)
return 0;
}
static cell_t GetContextTrace(IPluginContext *pContext, const cell_t *params)
{
IContextTrace *pTrace = pContext->GetContextTrace();
Handle_t hndl = handlesys->CreateHandle(g_ContextTrace, pTrace, pContext->GetIdentity(), g_pCoreIdent, NULL);
if (hndl == BAD_HANDLE)
{
g_pSourcePawn2->FreeContextTrace(pTrace);
}
return hndl;
}
static cell_t GetContextTraceInfo(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = params[1];
HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent);
HandleError err;
IContextTrace *pTrace = NULL;
if ((err = handlesys->ReadHandle(hndl, g_ContextTrace, &sec, (void **)&pTrace)) != HandleError_None)
{
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
}
CallStackInfo stackInfo;
if (pTrace->GetTraceInfo(&stackInfo))
{
pContext->StringToLocalUTF8(params[2], params[3], stackInfo.filename, NULL);
pContext->StringToLocalUTF8(params[4], params[5], stackInfo.function, NULL);
cell_t *pLineNum;
pContext->LocalToPhysAddr(params[6], &pLineNum);
*pLineNum = stackInfo.line;
return 1;
}
return 0;
}
REGISTER_NATIVES(coreNatives)
{
{"ThrowError", ThrowError},
@@ -773,5 +828,7 @@ REGISTER_NATIVES(coreNatives)
{"RequireFeature", RequireFeature},
{"LoadFromAddress", LoadFromAddress},
{"StoreToAddress", StoreToAddress},
{"GetContextTrace", GetContextTrace},
{"GetContextTraceInfo", GetContextTraceInfo},
{NULL, NULL},
};
@@ -676,6 +676,31 @@ native LoadFromAddress(Address:addr, NumberType:size);
*/
native StoreToAddress(Address:addr, data, NumberType:size);
/**
* Returns a context trace for the current execution state that can be used to build a function call stack trace.
* Must be closed with CloseHandle().
*
* @return A handle representing a context trace.
*/
native Handle:GetContextTrace();
/**
* Gets a single stack trace entry from a context trace.
* This function will return false when there are no more entries in the trace.
*
* @param trace Context trace handle.
* @param fileName Character buffer to store plugin file name.
* @param maxFileName Maximum length of the fileName buffer.
* @param functionName Character buffer to store plugin function name.
* @param maxFunctionName Maximum length of the functionName buffer.
* @param line Variable to store the plugin source line number.
*
* @return True if the context trace contains more stack entries; otherwise, false.
*/
native bool:GetContextTraceInfo(Handle:trace, String:fileName[], maxFileName, String:functionName[], maxFunctionName, &line);
#include <helpers>
#include <entity>
#include <entity_prop_stocks>
@@ -60,6 +60,7 @@ namespace SourcePawn
{
class IVirtualMachine;
class IPluginRuntime;
class IContextTrace;
/* Parameter flags */
#define SM_PARAM_COPYBACK (1<<0) /**< Copy an array/reference back after call */
@@ -901,6 +902,11 @@ namespace SourcePawn
* @brief Clears the last native error.
*/
virtual void ClearLastNativeError() =0;
/**
* @brief Returns a context trace representing the current execution state.
*/
virtual IContextTrace *GetContextTrace() =0;
};
@@ -1361,6 +1367,13 @@ namespace SourcePawn
* @param tool Profiling tool.
*/
virtual void SetProfilingTool(IProfilingTool *tool) =0;
/**
* @brief Frees a context trace that was returned from a plugin context.
*
* @param context Context trace.
*/
virtual void FreeContextTrace(IContextTrace *trace) =0;
};
};
@@ -210,3 +210,8 @@ bool SourcePawnEngine2::InstallWatchdogTimer(size_t timeout_ms)
return g_WatchdogTimer.Initialize(timeout_ms);
}
void SourcePawnEngine2::FreeContextTrace(IContextTrace *trace)
{
delete trace;
}
View
@@ -27,6 +27,7 @@ namespace SourcePawn
void Shutdown();
IPluginRuntime *CreateEmptyRuntime(const char *name, uint32_t memory);
bool InstallWatchdogTimer(size_t timeout_ms);
void FreeContextTrace(IContextTrace *trace);
bool SetJitEnabled(bool enabled) {
jit_enabled_ = enabled;
@@ -859,3 +859,8 @@ void BaseContext::ClearLastNativeError()
{
m_ctx.n_err = SP_ERROR_NONE;
}
IContextTrace *BaseContext::GetContextTrace()
{
return new CContextTrace(m_pRuntime, SP_ERROR_NONE, NULL, 0);
}
@@ -94,6 +94,7 @@ class BaseContext : public IPluginContext
bool GetKey(int k, void **value);
void Refresh();
void ClearLastNativeError();
IContextTrace *GetContextTrace();
public:
bool IsInExec();
private:

0 comments on commit a87226f

Please sign in to comment.