Skip to content
This repository has been archived by the owner on Nov 15, 2021. It is now read-only.

Commit

Permalink
Expose stack context traces to SourcePawn.
Browse files Browse the repository at this point in the history
  • Loading branch information
voided committed Sep 25, 2014
1 parent 9eb1b3e commit a87226f
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 2 deletions.
61 changes: 59 additions & 2 deletions core/logic/smn_core.cpp
Expand Up @@ -50,6 +50,7 @@
#endif

HandleType_t g_PlIter;
HandleType_t g_ContextTrace;

IForward *g_OnLogAction = NULL;

Expand All @@ -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,
Expand All @@ -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;
Expand Down Expand Up @@ -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},
Expand Down Expand Up @@ -773,5 +828,7 @@ REGISTER_NATIVES(coreNatives)
{"RequireFeature", RequireFeature},
{"LoadFromAddress", LoadFromAddress},
{"StoreToAddress", StoreToAddress},
{"GetContextTrace", GetContextTrace},
{"GetContextTraceInfo", GetContextTraceInfo},
{NULL, NULL},
};
25 changes: 25 additions & 0 deletions plugins/include/sourcemod.inc
Expand Up @@ -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>
Expand Down
13 changes: 13 additions & 0 deletions public/sourcepawn/sp_vm_api.h
Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
};


Expand Down Expand Up @@ -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;
};
};

Expand Down
5 changes: 5 additions & 0 deletions sourcepawn/jit/engine2.cpp
Expand Up @@ -210,3 +210,8 @@ bool SourcePawnEngine2::InstallWatchdogTimer(size_t timeout_ms)
return g_WatchdogTimer.Initialize(timeout_ms);
}

void SourcePawnEngine2::FreeContextTrace(IContextTrace *trace)
{
delete trace;
}

1 change: 1 addition & 0 deletions sourcepawn/jit/engine2.h
Expand Up @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions sourcepawn/jit/sp_vm_basecontext.cpp
Expand Up @@ -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);
}
1 change: 1 addition & 0 deletions sourcepawn/jit/sp_vm_basecontext.h
Expand Up @@ -94,6 +94,7 @@ class BaseContext : public IPluginContext
bool GetKey(int k, void **value);
void Refresh();
void ClearLastNativeError();
IContextTrace *GetContextTrace();
public:
bool IsInExec();
private:
Expand Down

0 comments on commit a87226f

Please sign in to comment.