Add LogStackTrace native (#685)

This commit is contained in:
Michael Flaherty 2018-06-19 23:18:37 -07:00 committed by Kyle Sanderson
parent b9b6832a11
commit 9ceb1af4fe
3 changed files with 54 additions and 11 deletions

View File

@ -29,11 +29,11 @@
* Version: $Id$ * Version: $Id$
*/ */
#include <ISourceMod.h>
#include <IPluginSys.h> #include <IPluginSys.h>
#include <stdarg.h> #include <stdarg.h>
#include "DebugReporter.h" #include "DebugReporter.h"
#include "Logger.h" #include "Logger.h"
#include <am-string.h>
DebugReport g_DbgReporter; DebugReport g_DbgReporter;
@ -194,35 +194,53 @@ void DebugReport::ReportError(const IErrorReport &report, IFrameIterator &iter)
g_Logger.LogError("[SM] Blaming: %s", blame); g_Logger.LogError("[SM] Blaming: %s", blame);
} }
if (!iter.Done()) ke::Vector<ke::AString> arr = GetStackTrace(&iter);
for (size_t i = 0; i < arr.length(); i++)
{ {
g_Logger.LogError("[SM] Call stack trace:"); g_Logger.LogError("%s", arr[i].chars());
}
}
for (int index = 0; !iter.Done(); iter.Next(), index++) ke::Vector<ke::AString> DebugReport::GetStackTrace(IFrameIterator *iter)
{
char temp[3072];
ke::Vector<ke::AString> trace;
iter->Reset();
if (!iter->Done())
{
trace.append("[SM] Call stack trace:");
for (int index = 0; !iter->Done(); iter->Next(), index++)
{ {
const char *fn = iter.FunctionName(); const char *fn = iter->FunctionName();
if (!fn) if (!fn)
{ {
fn = "<unknown function>"; fn = "<unknown function>";
} }
if (iter.IsNativeFrame()) if (iter->IsNativeFrame())
{ {
g_Logger.LogError("[SM] [%d] %s", index, fn); g_pSM->Format(temp, sizeof(temp), "[SM] [%d] %s", index, fn);
trace.append(temp);
continue; continue;
} }
if (iter.IsScriptedFrame()) if (iter->IsScriptedFrame())
{ {
const char *file = iter.FilePath(); const char *file = iter->FilePath();
if (!file) if (!file)
{ {
file = "<unknown>"; file = "<unknown>";
} }
g_Logger.LogError("[SM] [%d] Line %d, %s::%s", g_pSM->Format(temp, sizeof(temp), "[SM] [%d] Line %d, %s::%s",
index, index,
iter.LineNumber(), iter->LineNumber(),
file, file,
fn); fn);
trace.append(temp);
} }
} }
} }
return trace;
} }

View File

@ -34,6 +34,8 @@
#include "sp_vm_api.h" #include "sp_vm_api.h"
#include "common_logic.h" #include "common_logic.h"
#include <am-vector.h>
#include <am-string.h>
class DebugReport : class DebugReport :
public SMGlobalClass, public SMGlobalClass,
@ -48,6 +50,7 @@ public:
void GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...); void GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...);
void GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err, const char *message, va_list ap); void GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err, const char *message, va_list ap);
void GenerateCodeError(IPluginContext *ctx, uint32_t code_addr, int err, const char *message, ...); void GenerateCodeError(IPluginContext *ctx, uint32_t code_addr, int err, const char *message, ...);
ke::Vector<ke::AString> GetStackTrace(IFrameIterator *iter);
private: private:
int _GetPluginIndex(IPluginContext *ctx); int _GetPluginIndex(IPluginContext *ctx);
}; };

View File

@ -937,6 +937,27 @@ static cell_t FrameIterator_GetFilePath(IPluginContext *pContext, const cell_t *
return 0; return 0;
} }
static cell_t LogStackTrace(IPluginContext *pContext, const cell_t *params)
{
char buffer[512];
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1);
IFrameIterator *it = pContext->CreateFrameIterator();
ke::Vector<ke::AString> arr = g_DbgReporter.GetStackTrace(it);
pContext->DestroyFrameIterator(it);
IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
g_Logger.LogError("[SM] Stack trace requested: %s", buffer);
g_Logger.LogError("[SM] Called from: %s", pPlugin->GetFilename());
for (size_t i = 0; i < arr.length(); i)
{
g_Logger.LogError("%s", arr[i].chars());
}
return 0;
}
REGISTER_NATIVES(coreNatives) REGISTER_NATIVES(coreNatives)
{ {
{"ThrowError", ThrowError}, {"ThrowError", ThrowError},
@ -967,6 +988,7 @@ REGISTER_NATIVES(coreNatives)
{"StoreToAddress", StoreToAddress}, {"StoreToAddress", StoreToAddress},
{"IsNullVector", IsNullVector}, {"IsNullVector", IsNullVector},
{"IsNullString", IsNullString}, {"IsNullString", IsNullString},
{"LogStackTrace", LogStackTrace},
{"FrameIterator.FrameIterator", FrameIterator_Create}, {"FrameIterator.FrameIterator", FrameIterator_Create},
{"FrameIterator.Next", FrameIterator_Next}, {"FrameIterator.Next", FrameIterator_Next},