forked from dantmnf/NCSIOverride
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathshim.c
137 lines (111 loc) · 3.76 KB
/
shim.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
typedef void (*FUNCSHIM)();
void shim_prepare();
/* system detection */
#if defined(__i386__) || defined(_M_IX86)
#define SHIM_ARCH_X86
#elif defined(__x86_64__) || defined(__amd64__) || defined(_M_X64)
#define SHIM_ARCH_AMD64
#elif defined(__aarch64__) || defined(_M_ARM64)
#define SHIM_ARCH_AARCH64
#endif
#ifdef _MSC_VER
#define SHIM_COMPILER_MSVC_FLAVORED
#endif
#if defined(__GNUC__) || defined(__clang__)
#define SHIM_COMPILER_GNU_FLAVORED
#endif
#if defined(SHIM_ARCH_AMD64)
#define MANGLE(x) x
#elif defined(SHIM_ARCH_X86)
#define MANGLE(x) "_" x
#elif defined(SHIM_ARCH_AARCH64)
#error aarch64 not supported yet
#endif
#if !defined(SHIM_USE_EXTERNAL_ENTRY) && defined(SHIM_COMPILER_MSVC_FLAVORED) && defined(SHIM_ARCH_X86)
#define DECLARE_SHIM(name) \
FUNCSHIM p##name; \
__declspec(naked) void Shim##name() { \
__asm call shim_prepare \
__asm jmp [p##name] \
}
#elif !defined(SHIM_USE_EXTERNAL_ENTRY) && defined(SHIM_COMPILER_GNU_FLAVORED)
#define BEGIN_NAKED_FUNCTION(name) __asm__(".align 8"); \
__asm__(MANGLE(#name) ":"); \
__asm__(".globl " MANGLE(#name));
#define END_NAKED_FUNCTION()
#if defined(SHIM_ARCH_AMD64)
BEGIN_NAKED_FUNCTION(shim_prepare2)
__asm__("cmpl $0, " MANGLE("shim_prepared") "(%rip)");
__asm__("jz 114514f");
__asm__("ret");
__asm__("114514:");
__asm__("push %r9");
__asm__("push %r8");
__asm__("push %rdx");
__asm__("push %rcx");
__asm__("call " MANGLE("shim_prepare"));
__asm__("pop %rcx");
__asm__("pop %rdx");
__asm__("pop %r8");
__asm__("pop %r9");
__asm__("ret");
END_NAKED_FUNCTION()
#define DECLARE_SHIM(name) \
FUNCSHIM p##name; \
BEGIN_NAKED_FUNCTION( Shim##name ) \
__asm__ ("call " MANGLE("shim_prepare2")); \
__asm__ ("jmp *" MANGLE("p" #name) "(%rip)"); \
END_NAKED_FUNCTION()
#elif defined(SHIM_ARCH_X86)
BEGIN_NAKED_FUNCTION(shim_prepare2)
__asm__("cmpl $0, " MANGLE("shim_prepared"));
__asm__("jz 114514f");
__asm__("ret");
__asm__("114514:");
__asm__("jmp " MANGLE("shim_prepare"));
END_NAKED_FUNCTION()
#define DECLARE_SHIM(name) \
FUNCSHIM p##name; \
BEGIN_NAKED_FUNCTION( Shim##name ) \
__asm__ ("call " MANGLE("shim_prepare2")); \
__asm__ ("jmp *" MANGLE("p" #name)); \
END_NAKED_FUNCTION()
#endif
#else
#define DECLARE_SHIM(name) \
FUNCSHIM p##name; \
extern void Shim##name();
#endif
#define FILL_SHIM(name) do {p##name = (FUNCSHIM)GetProcAddress(hDll, #name);} while(0);
#include <windows.h>
static HMODULE hDll;
volatile LONG shim_preparing = 0, shim_prepared = 0;
__declspec(noinline) static HMODULE LoadTargetLibrary();
__declspec(noinline) static void FillShims();
#define SHIM_DECLARE
#define SHIM DECLARE_SHIM
#include "shim_declare.h"
#undef SHIM
#undef SHIM_DECLARE
static void FillShims() {
#define SHIM_FILL
#define SHIM FILL_SHIM
#include "shim_declare.h"
#undef SHIM
#undef SHIM_FILL
}
void shim_prepare() {
if (shim_prepared) return;
if (InterlockedCompareExchange(&shim_preparing, 1, 0) == 1) {
// yield if another thread is preparing
while (!shim_prepared) SwitchToThread();
// prepared by other thread
return;
}
hDll = LoadTargetLibrary();
if (hDll) {
FillShims();
shim_prepared = 1;
}
InterlockedCompareExchange(&shim_preparing, 0, 1);
}