forked from alexfreud/winamp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathglue_x86_64.h
261 lines (213 loc) · 7.86 KB
/
glue_x86_64.h
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
#ifndef _NSEEL_GLUE_X86_64_H_
#define _NSEEL_GLUE_X86_64_H_
#define GLUE_MAX_FPSTACK_SIZE 8
#define GLUE_JMP_SET_OFFSET(endOfInstruction,offset) (((int *)(endOfInstruction))[-1] = (offset))
#define GLUE_PREFER_NONFP_DV_ASSIGNS
static const unsigned char GLUE_JMP_NC[] = { 0xE9, 0,0,0,0, }; // jmp<offset>
static const unsigned char GLUE_JMP_IF_P1_Z[] = {0x85, 0xC0, 0x0F, 0x84, 0,0,0,0 }; // test eax, eax, jz
static const unsigned char GLUE_JMP_IF_P1_NZ[] = {0x85, 0xC0, 0x0F, 0x85, 0,0,0,0 }; // test eax, eax, jnz
#define GLUE_FUNC_ENTER_SIZE 0
#define GLUE_FUNC_LEAVE_SIZE 0
const static unsigned int GLUE_FUNC_ENTER[1];
const static unsigned int GLUE_FUNC_LEAVE[1];
// on x86-64:
// stack is always 16 byte aligned
// pushing values to the stack (for eel functions) has alignment pushed first, then value (value is at the lower address)
// pushing pointers to the stack has the pointer pushed first, then the alignment (pointer is at the higher address)
#define GLUE_MOV_PX_DIRECTVALUE_SIZE 10
static void GLUE_MOV_PX_DIRECTVALUE_GEN(void *b, INT_PTR v, int wr) {
const static unsigned short tab[3] =
{
0xB848 /* mov rax, dv*/,
0xBF48 /* mov rdi, dv */ ,
0xB948 /* mov rcx, dv */
};
unsigned short *bb = (unsigned short *)b;
*bb++ = tab[wr]; // mov rax, directvalue
*(INT_PTR *)bb = v;
}
const static unsigned char GLUE_PUSH_P1[2]={ 0x50,0x50}; // push rax (pointer); push rax (alignment)
#define GLUE_POP_PX_SIZE 2
static void GLUE_POP_PX(void *b, int wv)
{
static const unsigned char tab[3][GLUE_POP_PX_SIZE]=
{
{0x58,/*pop eax*/ 0x58}, // pop alignment, then pop pointer
{0x5F,/*pop edi*/ 0x5F},
{0x59,/*pop ecx*/ 0x59},
};
memcpy(b,tab[wv],GLUE_POP_PX_SIZE);
}
static const unsigned char GLUE_PUSH_P1PTR_AS_VALUE[] =
{
0x50, /*push rax - for alignment */
0xff, 0x30, /* push qword [rax] */
};
static int GLUE_POP_VALUE_TO_ADDR(unsigned char *buf, void *destptr) // trashes P2 (rdi) and P3 (rcx)
{
if (buf)
{
*buf++ = 0x48; *buf++ = 0xB9; *(void **) buf = destptr; buf+=8; // mov rcx, directvalue
*buf++ = 0x8f; *buf++ = 0x01; // pop qword [rcx]
*buf++ = 0x5F ; // pop rdi (alignment, safe to trash rdi though)
}
return 1+10+2;
}
static int GLUE_COPY_VALUE_AT_P1_TO_PTR(unsigned char *buf, void *destptr) // trashes P2/P3
{
if (buf)
{
*buf++ = 0x48; *buf++ = 0xB9; *(void **) buf = destptr; buf+=8; // mov rcx, directvalue
*buf++ = 0x48; *buf++ = 0x8B; *buf++ = 0x38; // mov rdi, [rax]
*buf++ = 0x48; *buf++ = 0x89; *buf++ = 0x39; // mov [rcx], rdi
}
return 3 + 10 + 3;
}
static int GLUE_POP_FPSTACK_TO_PTR(unsigned char *buf, void *destptr)
{
if (buf)
{
*buf++ = 0x48;
*buf++ = 0xB8;
*(void **) buf = destptr; buf+=8; // mov rax, directvalue
*buf++ = 0xDD; *buf++ = 0x18; // fstp qword [rax]
}
return 2+8+2;
}
#define GLUE_SET_PX_FROM_P1_SIZE 3
static void GLUE_SET_PX_FROM_P1(void *b, int wv)
{
static const unsigned char tab[3][GLUE_SET_PX_FROM_P1_SIZE]={
{0x90,0x90,0x90}, // should never be used! (nopnop)
{0x48,0x89,0xC7}, // mov rdi, rax
{0x48,0x89,0xC1}, // mov rcx, rax
};
memcpy(b,tab[wv],GLUE_SET_PX_FROM_P1_SIZE);
}
#define GLUE_POP_FPSTACK_SIZE 2
static const unsigned char GLUE_POP_FPSTACK[2] = { 0xDD, 0xD8 }; // fstp st0
static const unsigned char GLUE_POP_FPSTACK_TOSTACK[] = {
0x48, 0x81, 0xEC, 16, 0,0,0, // sub rsp, 16
0xDD, 0x1C, 0x24 // fstp qword (%rsp)
};
static const unsigned char GLUE_POP_FPSTACK_TO_WTP[] = {
0xDD, 0x1E, /* fstp qword [rsi] */
0x48, 0x81, 0xC6, 8, 0,0,0,/* add rsi, 8 */
};
#define GLUE_SET_PX_FROM_WTP_SIZE 3
static void GLUE_SET_PX_FROM_WTP(void *b, int wv)
{
static const unsigned char tab[3][GLUE_SET_PX_FROM_WTP_SIZE]={
{0x48, 0x89,0xF0}, // mov rax, rsi
{0x48, 0x89,0xF7}, // mov rdi, rsi
{0x48, 0x89,0xF1}, // mov rcx, rsi
};
memcpy(b,tab[wv],GLUE_SET_PX_FROM_WTP_SIZE);
}
#define GLUE_PUSH_VAL_AT_PX_TO_FPSTACK_SIZE 2
static void GLUE_PUSH_VAL_AT_PX_TO_FPSTACK(void *b, int wv)
{
static const unsigned char tab[3][GLUE_PUSH_VAL_AT_PX_TO_FPSTACK_SIZE]={
{0xDD,0x00}, // fld qword [rax]
{0xDD,0x07}, // fld qword [rdi]
{0xDD,0x01}, // fld qword [rcx]
};
memcpy(b,tab[wv],GLUE_PUSH_VAL_AT_PX_TO_FPSTACK_SIZE);
}
static unsigned char GLUE_POP_STACK_TO_FPSTACK[] = {
0xDD, 0x04, 0x24, // fld qword (%rsp)
0x48, 0x81, 0xC4, 16, 0,0,0, // add rsp, 16
};
#define GLUE_POP_FPSTACK_TO_WTP_TO_PX_SIZE (GLUE_SET_PX_FROM_WTP_SIZE + sizeof(GLUE_POP_FPSTACK_TO_WTP))
static void GLUE_POP_FPSTACK_TO_WTP_TO_PX(unsigned char *buf, int wv)
{
GLUE_SET_PX_FROM_WTP(buf,wv);
memcpy(buf + GLUE_SET_PX_FROM_WTP_SIZE,GLUE_POP_FPSTACK_TO_WTP,sizeof(GLUE_POP_FPSTACK_TO_WTP));
};
const static unsigned char GLUE_RET=0xC3;
static int GLUE_RESET_WTP(unsigned char *out, void *ptr)
{
if (out)
{
*out++ = 0x48;
*out++ = 0xBE; // mov rsi, constant64
*(void **)out = ptr;
out+=sizeof(void *);
}
return 2+sizeof(void *);
}
extern void win64_callcode(INT_PTR code, INT_PTR ram_tab);
#define GLUE_CALL_CODE(bp, cp, rt) win64_callcode(cp, rt)
static unsigned char *EEL_GLUE_set_immediate(void *_p, INT_PTR newv)
{
char *p=(char*)_p;
INT_PTR scan = 0xFEFEFEFEFEFEFEFE;
while (*(INT_PTR *)p != scan) p++;
*(INT_PTR *)p = newv;
return (unsigned char *) (((INT_PTR*)p)+1);
}
#define INT_TO_LECHARS(x) ((x)&0xff),(((x)>>8)&0xff), (((x)>>16)&0xff), (((x)>>24)&0xff)
#define GLUE_INLINE_LOOPS
static const unsigned char GLUE_LOOP_LOADCNT[]={
0xDD, 0x0E, //fistTp qword [rsi]
0x48, 0x8B, 0x0E, // mov rcx, [rsi]
0x48, 0x81, 0xf9, 1,0,0,0, // cmp rcx, 1
0x0F, 0x8C, 0,0,0,0, // JL <skipptr>
};
static const unsigned char GLUE_LOOP_CLAMPCNT[]={
0x48, 0x81, 0xf9, INT_TO_LECHARS(NSEEL_LOOPFUNC_SUPPORT_MAXLEN), // cmp rcx, NSEEL_LOOPFUNC_SUPPORT_MAXLEN
0x0F, 0x8C, 10,0,0,0, // JL over-the-mov
0x48, 0xB9, INT_TO_LECHARS(NSEEL_LOOPFUNC_SUPPORT_MAXLEN), 0,0,0,0, // mov rcx, NSEEL_LOOPFUNC_SUPPORT_MAXLEN
};
static const unsigned char GLUE_LOOP_BEGIN[]={
0x56, //push rsi
0x51, // push rcx
};
static const unsigned char GLUE_LOOP_END[]={
0x59, //pop rcx
0x5E, // pop rsi
0xff, 0xc9, // dec rcx
0x0f, 0x85, 0,0,0,0, // jnz ...
};
static const unsigned char GLUE_WHILE_SETUP[]={
0x48, 0xB9, INT_TO_LECHARS(NSEEL_LOOPFUNC_SUPPORT_MAXLEN), 0,0,0,0, // mov rcx, NSEEL_LOOPFUNC_SUPPORT_MAXLEN
};
static const unsigned char GLUE_WHILE_BEGIN[]={
0x56, //push rsi
0x51, // push rcx
};
static const unsigned char GLUE_WHILE_END[]={
0x59, //pop rcx
0x5E, // pop rsi
0xff, 0xc9, // dec rcx
0x0f, 0x84, 0,0,0,0, // jz endpt
};
static const unsigned char GLUE_WHILE_CHECK_RV[] = {
0x85, 0xC0, // test eax, eax
0x0F, 0x85, 0,0,0,0 // jnz looppt
};
static const unsigned char GLUE_SET_P1_Z[] = { 0x48, 0x29, 0xC0 }; // sub rax, rax
static const unsigned char GLUE_SET_P1_NZ[] = { 0xb0, 0x01 }; // mov al, 1
#define GLUE_HAS_FXCH
static const unsigned char GLUE_FXCH[] = {0xd9, 0xc9};
#define GLUE_HAS_FLDZ
static const unsigned char GLUE_FLDZ[] = {0xd9, 0xee};
#define GLUE_HAS_FLD1
static const unsigned char GLUE_FLD1[] = {0xd9, 0xe8};
static EEL_F negativezeropointfive=-0.5f;
static EEL_F onepointfive=1.5f;
#define GLUE_INVSQRT_NEEDREPL &negativezeropointfive, &onepointfive,
#define GLUE_HAS_NATIVE_TRIGSQRTLOG
static void *GLUE_realAddress(void *fn, void *fn_e, int *size)
{
static const unsigned char sig[12] = { 0x89, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 };
unsigned char *p = (unsigned char *)fn;
while (memcmp(p,sig,sizeof(sig))) p++;
p+=sizeof(sig);
fn = p;
while (memcmp(p,sig,sizeof(sig))) p++;
*size = p - (unsigned char *)fn;
return fn;
}
// end of x86-64
#endif