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
|
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/mman.h>
#include <errno.h>
#include "wine_tools.h"
#include "debug.h"
#include "box64context.h"
#include "custommem.h"
typedef struct wine_prereserve_s
{
void* addr;
size_t size;
} wine_prereserve_t;
#ifdef BOX32
typedef struct wine_prereserve_32_s
{
ptr_t addr;
ulong_t size;
} wine_prereserve_32_t;
#include "box32.h"
#endif
// only the prereseve argument is reserved, not the other zone that wine-preloader reserve
static wine_prereserve_t my_wine_reserve[] = {{(void*)0x00010000, 0x00008000}, {(void*)0x00110000, 0x30000000}, {(void*)0x7f000000, 0x03000000}, {0, 0}, {0, 0}};
int wine_preloaded = 0;
static int get_prereserve(const char* reserve, void** addr, size_t* size)
{
if(!reserve)
return 0;
uintptr_t r = 0;
int first = 1;
while(*reserve) {
// numbers reading
if(*reserve>='0' && *reserve<='9') r=r*16+(*reserve)-'0';
else if(*reserve>='A' && *reserve<='F') r=r*16+(*reserve)-'A'+10;
else if(*reserve>='a' && *reserve<='f') r=r*16+(*reserve)-'a'+10;
else if(*reserve=='-') {if(first) {*addr=(void*)(r&~(box64_pagesize-1)); r=0; first=0;} else {printf_log(LOG_NONE, "Warning, Wine prereserve badly formatted\n"); return 0;}}
else {printf_log(LOG_INFO, "Warning, Wine prereserve badly formatted\n"); return 0;}
++reserve;
}
*size = r;
return 1;
}
static void add_no_overlap(void* addr, size_t size)
{
int idx = 0;
while(my_wine_reserve[idx].addr && my_wine_reserve[idx].size) {
if(addr>=my_wine_reserve[idx].addr && addr<my_wine_reserve[idx].addr+my_wine_reserve[idx].size) {
// overlap
if (addr+size > my_wine_reserve[idx].addr+my_wine_reserve[idx].size)
// need adjust size
my_wine_reserve[idx].size = (intptr_t)addr-(intptr_t)my_wine_reserve[idx].addr+size;
return;
}
++idx;
}
my_wine_reserve[idx].addr = addr;
my_wine_reserve[idx].size = size;
}
static void remove_prereserve(int idx)
{
while(my_wine_reserve[idx].size) {
my_wine_reserve[idx].addr = my_wine_reserve[idx+1].addr;
my_wine_reserve[idx].size = my_wine_reserve[idx+1].size;
++idx;
}
}
void wine_prereserve(const char* reserve)
{
init_custommem_helper(my_context);
void* addr = NULL;
size_t size = 0;
if(get_prereserve(reserve, &addr, &size)) {
add_no_overlap(addr, size);
}
int idx = 0;
while(my_wine_reserve[idx].addr && my_wine_reserve[idx].size) {
void* ret = NULL;
int isfree = isBlockFree(my_wine_reserve[idx].addr, my_wine_reserve[idx].size);
if(isfree) ret=mmap(my_wine_reserve[idx].addr, my_wine_reserve[idx].size, 0, MAP_FIXED|MAP_PRIVATE|MAP_ANON|MAP_NORESERVE, -1, 0); else ret = NULL;
if(!isfree || (ret!=my_wine_reserve[idx].addr)) {
if(addr>=(void*)0x10000LL)
printf_log(LOG_INFO, "Warning, prereserve of %p:0x%lx is not free\n", my_wine_reserve[idx].addr, my_wine_reserve[idx].size);
if(ret)
munmap(ret, my_wine_reserve[idx].size);
remove_prereserve(idx);
} else {
setProtection_mmap((uintptr_t)my_wine_reserve[idx].addr, my_wine_reserve[idx].size, 0);
printf_log(/*LOG_DEBUG*/LOG_INFO, "WINE prereserve of %p:0x%lx done\n", my_wine_reserve[idx].addr, my_wine_reserve[idx].size);
++idx;
}
}
wine_preloaded = 1;
}
void* get_wine_prereserve()
{
if(!wine_preloaded)
wine_prereserve(NULL);
#ifdef BOX32
if(box64_is32bits) {
static wine_prereserve_32_t my_wine_reserve_32[5];
for(int i=0; i<5; ++i) {
my_wine_reserve_32[i].addr = to_ptrv(my_wine_reserve[i].addr);
my_wine_reserve_32[i].size = to_ulong(my_wine_reserve[i].size);
}
return &my_wine_reserve_32;
} else
#endif
return &my_wine_reserve;
}
#ifdef DYNAREC
void dynarec_wine_prereserve()
{
#if 0
// disable for now, as it break some installer
if(!wine_preloaded)
wine_prereserve(NULL);
// don't reserve the initial arbritrary block as "with linker", it's not true
for(int i=1; i<sizeof(my_wine_reserve)/sizeof(my_wine_reserve[0]); ++i)
if(my_wine_reserve[i].addr && my_wine_reserve[i].size)
addDBFromAddressRange((uintptr_t)my_wine_reserve[i].addr, my_wine_reserve[i].size); // prepare the prereserved area for exec, with linker
#endif
}
#endif
void DetectUnityPlayer(char* filename)
{
static int unityplayer_detected = 0;
if (filename && BOX64ENV(unityplayer) && !unityplayer_detected && !strcmp(filename, "unityplayer.dll")) {
printf_log(LOG_INFO, "Detected UnityPlayer.dll\n");
#ifdef DYNAREC
if (!BOX64ENV(dynarec_strongmem)) {
SET_BOX64ENV(dynarec_strongmem, 1);
PrintEnvVariables(&box64env, LOG_INFO);
}
#endif
unityplayer_detected = 1;
}
}
|