Skip to content

Commit 9c942c4

Browse files
committed
Added scheduled script profiling
1 parent a120d60 commit 9c942c4

5 files changed

Lines changed: 168 additions & 0 deletions

File tree

src/HookManager.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ enum class hookTypes {
1414
scopeCompleted,
1515
frameEnd,
1616
compileCacheIns,
17+
sVMSimulate,
1718
End
1819
};
1920

src/hooks.asm

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,56 @@ _TEXT SEGMENT
215215

216216

217217

218+
EXTERN vmSimulateJmpback: qword
219+
220+
PUBLIC sVMSimStableReal
221+
sVMSimStableReal PROC
222+
;fixup
223+
push rbx
224+
sub rsp, 70h
225+
cmp byte ptr [rcx+32h], 0
226+
mov rbx, rcx
227+
movaps xmmword ptr [rsp+50h], xmm6
228+
movaps xmm6, xmm2
229+
230+
jmp vmSimulateJmpback;
231+
sVMSimStableReal ENDP
232+
233+
234+
235+
PUBLIC sVMSimProfReal
236+
sVMSimProfReal PROC
237+
;fixup
238+
mov r11, rsp
239+
push rbp
240+
push rbx
241+
lea rbp, [r11-5Fh]
242+
sub rsp, 0A8h
243+
cmp byte ptr [rcx+32h], 0
244+
mov rbx, rcx
245+
movaps xmmword ptr [r11-38h], xmm6
246+
movaps xmm6, xmm2
247+
248+
jmp vmSimulateJmpback;
249+
sVMSimProfReal ENDP
250+
251+
252+
253+
254+
255+
256+
257+
258+
259+
260+
261+
262+
263+
264+
265+
266+
267+
218268

219269

220270
_TEXT ENDS

src/scheduledProfiler.cpp

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#include "scheduledProfiler.hpp"
2+
#include "ProfilerAdapter.hpp"
3+
#include "AdapterTracy.hpp"
4+
#include <client.hpp>
5+
#include <shared_mutex>
6+
#include "scriptProfiler.hpp"
7+
#include "SignalSlot.hpp"
8+
9+
#if _WIN32
10+
#include <windows.h>
11+
#endif
12+
13+
14+
extern "C" {
15+
uintptr_t vmSimulateJmpback;
16+
17+
bool __fastcall sVMSimStableReal(uintptr_t, float deltaT, float timeLimit);
18+
bool __fastcall sVMSimProfReal(uintptr_t, float deltaT, float timeLimit);
19+
bool VMSimulateHook(uintptr_t, float deltaT, float timeLimit);
20+
21+
decltype(sVMSimProfReal)* sVMSimReal = sVMSimProfReal;
22+
}
23+
24+
25+
HookManager hooks;
26+
27+
28+
29+
// "scrVM" prof scope
30+
HookManager::Pattern pat_vmSimulateProf{
31+
"xxxxxxxx?xxxxxxxxx??xxxxxxx?xxxx?xxxxxx?xxxxxxxxxxxx?????xxxx????xxxx????xxxx????xxx????xxxx????xxxx????x?x????xxx????xxx????xxx????xxx????xxxxxx????xxxxx????x????xx????xx?????xxx????xxxx????xxxxxx?xx?????xx?xxx?x?xxx????x?xxx?xx????xx????x?xxx????xx??x?xxxxxxxxxxxx?x?x????xxx?x?xxx?xxx?xxx????xxx????xxxxxxx????xxx?xxx?xxx????xxx?xxxx????xxxxxxx?xxxxx"sv,
32+
"\x4C\x8B\xDC\x55\x53\x49\x8D\x6B\x00\x48\x81\xEC\xA8\x00\x00\x00\x80\x79\x00\x00\x48\x8B\xD9\x41\x0F\x29\x73\x00\x0F\x28\xF2\x75\x00\x32\xC0\x41\x0F\x28\x73\x00\x48\x81\xC4\xA8\x00\x00\x00\x5B\x5D\xC3\x80\x3D\x00\x00\x00\x00\x00\x48\x89\xB4\x24\x00\x00\x00\x00\x48\x89\xBC\x24\x00\x00\x00\x00\x4C\x89\xA4\x24\x00\x00\x00\x00\x4C\x8D\x25\x00\x00\x00\x00\x4C\x89\xB4\x24\x00\x00\x00\x00\x4C\x89\xBC\x24\x00\x00\x00\x00\x75\x00\xE8\x00\x00\x00\x00\x48\x8D\x15\x00\x00\x00\x00\x4C\x89\x25\x00\x00\x00\x00\x4C\x8D\x05\x00\x00\x00\x00\x48\x89\x15\x00\x00\x00\x00\x44\x8B\xC8\x4C\x89\x05\x00\x00\x00\x00\x49\x8B\xCC\x89\x05\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x89\x05\x00\x00\x00\x00\xC6\x05\x00\x00\x00\x00\x00\x48\x8D\x3D\x00\x00\x00\x00\x48\x8B\xCF\xE8\x00\x00\x00\x00\x45\x33\xFF\x48\x89\x7D\x00\x83\x3D\x00\x00\x00\x00\x00\x88\x45\x00\x4C\x89\x7D\x00\x74\x00\x44\x38\x3D\x00\x00\x00\x00\x75\x00\x84\xC0\x74\x00\xFF\x15\x00\x00\x00\x00\x39\x05\x00\x00\x00\x00\x75\x00\x44\x38\x3D\x00\x00\x00\x00\xC6\x45\x00\x00\x74\x00\x0F\x31\x48\xC1\xE2\x20\x48\x0B\xC2\x48\x89\x45\x00\xEB\x00\xE8\x00\x00\x00\x00\x48\x89\x45\x00\xEB\x00\x44\x88\x7D\x00\x4C\x89\x7D\x00\x44\x38\x3D\x00\x00\x00\x00\x48\x8D\x3D\x00\x00\x00\x00\xBE\xFF\xFF\xFF\xFF\x0F\x84\x00\x00\x00\x00\x48\x8B\x43\x00\x48\x8D\x55\x00\x48\x8B\x88\x00\x00\x00\x00\x44\x8B\x71\x00\x48\x8B\xCB\xE8\x00\x00\x00\x00\x4C\x8B\x00\x4D\x85\xC0\x74\x00\x49\x83\xC0\x10\xEB"sv
33+
};
34+
35+
// "Global namespace not passed (script %s)",
36+
HookManager::Pattern pat_vmSimulatePerf{
37+
"xxxxxxxx??xxxxxxx?xxxx?xxxxxx?xxxxxxxxxx????xxxx????xxx?xxxx?xxxx?xxxx?xxx????xx????xxx????xxx????xxx??xxxx?x????xxx????xxxx?xxxxx?xxx?xxx????xxxxxxxxx?xxxxxx?xxxx?xxxxxxxx?xxx????xxx?xxx????xxxx?xxx?xxx????xx????xxx?xxx?xxxxx????xxxxxxxxxxxxxx?xxxx?x????xxx????xxxxx????xxx????xxx????xxxx????xxxx?xxx?xxx????xxxx?xxxx?xxxxxx?xxxx?xxxxx?xxxxx????xxx?xx?????x?xxx????xxx?xxx?xxxx?xxx?xxx?xxxx?xxxxxx?xxxx?xxxxx?xxx?xxx????xxxx?xx??x?xxx?x"sv,
38+
"\x40\x53\x48\x83\xEC\x70\x80\x79\x00\x00\x48\x8B\xD9\x0F\x29\x74\x24\x00\x0F\x28\xF2\x75\x00\x32\xC0\x0F\x28\x74\x24\x00\x48\x83\xC4\x70\x5B\xC3\x48\x89\xAC\x24\x00\x00\x00\x00\x48\x89\xB4\x24\x00\x00\x00\x00\x48\x8B\x71\x00\x48\x89\x7C\x24\x00\x4C\x89\x74\x24\x00\x48\x85\xF6\x75\x00\x40\x38\x35\x00\x00\x00\x00\x0F\x84\x00\x00\x00\x00\x48\x8D\x35\x00\x00\x00\x00\x48\x8D\x05\x00\x00\x00\x00\xC6\x44\x24\x00\x00\x48\x89\x44\x24\x00\xE8\x00\x00\x00\x00\x48\x8B\x3D\x00\x00\x00\x00\x48\x89\x44\x24\x00\xF3\x0F\x11\x74\x24\x00\xF0\xFF\x46\x00\x48\x89\x35\x00\x00\x00\x00\xBE\xFF\xFF\xFF\xFF\x48\x85\xFF\x74\x00\x8B\xC6\xF0\x0F\xC1\x47\x00\x83\xF8\x01\x75\x00\x48\x8B\x07\x48\x8B\xCF\xFF\x50\x00\x48\x8B\x2D\x00\x00\x00\x00\x48\x8B\x43\x00\x48\x89\x05\x00\x00\x00\x00\x48\x85\xED\x74\x00\x48\x8B\x4B\x00\x0F\xB6\x85\x00\x00\x00\x00\x88\x81\x00\x00\x00\x00\x48\x8B\x4B\x00\x4C\x8D\x4B\x00\x33\xC0\x48\x8D\x15\x00\x00\x00\x00\x48\x85\xDB\x44\x8B\xC6\x4C\x0F\x44\xC8\x48\x8D\x44\x24\x00\x48\x89\x44\x24\x00\xE8\x00\x00\x00\x00\x48\x8D\x0D\x00\x00\x00\x00\x44\x0F\xB6\xF0\xE8\x00\x00\x00\x00\x48\x8B\x0D\x00\x00\x00\x00\x48\x89\x2D\x00\x00\x00\x00\x48\x8B\xAC\x24\x00\x00\x00\x00\x48\x85\xFF\x74\x00\xF0\xFF\x47\x00\x48\x89\x3D\x00\x00\x00\x00\x48\x8B\x7C\x24\x00\x48\x85\xC9\x74\x00\x8B\xC6\xF0\x0F\xC1\x41\x00\x83\xF8\x01\x75\x00\x48\x8B\x01\xFF\x50\x00\x45\x84\xF6\x0F\x84\x00\x00\x00\x00\x48\x8B\x43\x00\x83\xB8\x00\x00\x00\x00\x00\x75\x00\x48\x8B\x80\x00\x00\x00\x00\x48\x8B\x4B\x00\x48\x8B\x50\x00\x48\x85\xD2\x74\x00\xF0\xFF\x42\x00\x48\x89\x53\x00\x48\x85\xC9\x74\x00\x8B\xC6\xF0\x0F\xC1\x41\x00\x83\xF8\x01\x75\x00\x48\x8B\x01\xFF\x50\x00\x48\x8B\x4B\x00\x48\x8B\x81\x00\x00\x00\x00\x48\x85\xC0\x74\x00\x80\x78\x00\x00\x74\x00\x48\x8B\x53\x00\xEB"sv
39+
};
40+
41+
42+
struct scriptVM {
43+
44+
uintptr_t vtable1;
45+
uintptr_t _a;
46+
uintptr_t _b;
47+
uintptr_t vtable2;
48+
intercept::types::vm_context* context;
49+
void* b;
50+
bool c;
51+
bool d;
52+
bool e;
53+
bool f;
54+
bool g; // 2.22
55+
56+
game_value argument;
57+
r_string name;
58+
};
59+
60+
61+
std::unordered_map<const char*, std::shared_ptr<ScopeInfo>> scopeCache;
62+
extern std::string getScriptName(const r_string& str, const r_string& filePath, uint32_t returnFirstLineIfNoName = 0);
63+
64+
bool VMSimulateHook(uintptr_t vmPtr, float deltaT, float timeLimit)
65+
{
66+
auto vm = (scriptVM*)vmPtr;
67+
68+
if (!vm->context)
69+
return sVMSimProfReal(vmPtr, deltaT, timeLimit);
70+
71+
auto tracyProf = std::reinterpret_pointer_cast<AdapterTracy>(GProfilerAdapter);
72+
73+
std::unordered_map<const char*, std::shared_ptr<ScopeInfo>>::iterator found = scopeCache.find(vm->context->sdoc.content.c_str());
74+
if (found == scopeCache.end())
75+
{
76+
auto name = r_string(getScriptName(vm->context->sdoc.content, vm->context->sdoc.sourcefile, 1));
77+
auto res = scopeCache.insert({ vm->context->sdoc.content.c_str(), tracyProf->createScope(name, vm->context->sdoc.sourcefile, 0) });
78+
found = res.first;
79+
}
80+
81+
auto tmp = tracyProf->enterScope(found->second);
82+
83+
auto res = sVMSimReal(vmPtr, deltaT, timeLimit);
84+
85+
return res;
86+
}
87+
88+
89+
void ScheduledProfiler::init() {
90+
91+
92+
if (hooks.placeHook(hookTypes::sVMSimulate, pat_vmSimulateProf, reinterpret_cast<uintptr_t>(VMSimulateHook), vmSimulateJmpback, 0x11)) {
93+
sVMSimReal = sVMSimProfReal;
94+
} else if (hooks.placeHook(hookTypes::sVMSimulate, pat_vmSimulatePerf, reinterpret_cast<uintptr_t>(VMSimulateHook), vmSimulateJmpback, 0x7)) {
95+
sVMSimReal = sVMSimStableReal;
96+
}
97+
98+
99+
}

src/scheduledProfiler.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
3+
4+
namespace ScheduledProfiler
5+
{
6+
void init();
7+
}

src/scriptProfiler.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <string>
2626
#include "NetworkProfiler.hpp"
2727
#include <pointers.hpp>
28+
#include "scheduledProfiler.hpp"
2829

2930

3031
using namespace intercept;
@@ -429,6 +430,13 @@ std::string getScriptName(const r_string& str, const r_string& filePath, uint32_
429430
//if (str.find("createProfileScope", 0) != -1) return "<unknown>"; //Don't remember why I did this :D
430431

431432
if (returnFirstLineIfNoName) {
433+
434+
size_t offset = 0;
435+
436+
while (offset < str.capacity() && std::isspace(str.c_str()[offset])) // Find first non-whitespace char, skip starting empty line
437+
++offset;
438+
439+
432440
auto linebreak = str.find("\n", 0);
433441
if (linebreak < 20) {
434442
auto linebreak2 = str.find("\n", linebreak + 1);
@@ -1640,6 +1648,9 @@ void scriptProfiler::preStart() {
16401648
//delete ins;
16411649
}
16421650
#endif
1651+
1652+
1653+
ScheduledProfiler::init();
16431654
}
16441655

16451656

0 commit comments

Comments
 (0)