diff --git a/appveyor.yml b/appveyor.yml index 690eba4..48b982e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,7 +5,7 @@ environment: install: - cd .. - git clone --depth=1 --branch=1.8-dev --recursive https://github.com/alliedmodders/sourcemod sourcemod-1.8 - - git clone --depth=1 --branch=master https://github.com/alliedmodders/ambuild + - git clone --depth=1 --branch=master --recursive https://github.com/alliedmodders/ambuild - cd ambuild - C:\python27\python.exe setup.py install - cd %APPVEYOR_BUILD_FOLDER% diff --git a/extension/extension.cpp b/extension/extension.cpp index e497399..271a226 100644 --- a/extension/extension.cpp +++ b/extension/extension.cpp @@ -135,6 +135,18 @@ char steamInf[1024]; char dumpStoragePath[512]; char logPath[512]; +struct ProfilerEntry { + ProfilerEntry(const char *pName, volatile void *stackVarPtr) { + strncpy(name, pName, sizeof(name)); + stackAddr = (uint64_t)stackVarPtr; + } + + uint64_t stackAddr; + char name[248]; +}; + +std::vector g_ProfilerEntries; + google_breakpad::ExceptionHandler *handler = NULL; #if defined _LINUX @@ -225,6 +237,25 @@ static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, } } + int count = g_ProfilerEntries.size(); + if (count > 0) { + sys_write(extra, "-------- SOURCEPAWN STACK BEGIN --------\n", 41); + for (int i = count - 1; i >= 0; --i) { + const ProfilerEntry &entry = g_ProfilerEntries[i]; + if (my_strcmp(entry.name, "EnterJIT") == 0) { + continue; + } + + char strAddr[32]; + my_uitos(strAddr, entry.stackAddr, my_uint_len(entry.stackAddr)); + sys_write(extra, strAddr, my_strlen(strAddr)); + sys_write(extra, " ", 1); + sys_write(extra, entry.name, my_strlen(entry.name)); + sys_write(extra, "\n", 1); + } + sys_write(extra, "-------- SOURCEPAWN STACK END --------\n", 39); + } + sys_close(extra); return succeeded; @@ -1097,6 +1128,56 @@ const char *GetCmdLine() return (const char *)(reinterpret_cast(cmdline)->*u.mfpnew)(); } +class LoggingProfilingTool: public IProfilingTool +{ + virtual const char *Name() { + return "Accelerator"; + } + + virtual const char *Description() { + return "Accelerator SourcePawn call stack collection."; + } + + virtual void RenderHelp(void (*render)(const char* fmt, ...)) { + + } + + virtual bool Start() { + return true; + } + + virtual void Stop(void (*render)(const char* fmt, ...)) { + + } + + virtual void Dump() { + + } + + virtual bool IsActive() { + return true; + } + + virtual bool IsAttached() { + return true; + } + + virtual void EnterScope(const char *group, const char *name) { + rootconsole->ConsolePrint("!!! EnterScope(\"%s\", \"%s\")", group, name); + + volatile int p; + g_ProfilerEntries.emplace_back(name, &p); + } + + virtual void LeaveScope() { + rootconsole->ConsolePrint("!!! LeaveScope()"); + + if (!g_ProfilerEntries.empty()) { + g_ProfilerEntries.pop_back(); + } + } +} g_ProfilingTool; + bool Accelerator::SDK_OnLoad(char *error, size_t maxlength, bool late) { sharesys->AddDependency(myself, "webternet.ext", true, true); @@ -1214,6 +1295,9 @@ bool Accelerator::SDK_OnLoad(char *error, size_t maxlength, bool late) } strncpy(crashSourceModVersion, spEnvironment->APIv2()->GetVersionString(), sizeof(crashSourceModVersion)); + + spEnvironment->APIv2()->SetProfilingTool(&g_ProfilingTool); + spEnvironment->APIv2()->EnableProfiling(); } while(false); plsys->AddPluginsListener(this);