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
|
#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"
typedef struct wine_prereserve_s
{
void* addr;
size_t size;
} wine_prereserve_t;
// 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_NONE, "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;
}
void wine_prereserve(const char* reserve)
{
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* p = mmap(my_wine_reserve[idx].addr, my_wine_reserve[idx].size,
PROT_NONE, /*MAP_FIXED |*/ MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, -1, 0);
if(p==(void*)-1 || p!=my_wine_reserve[idx].addr) {
printf_log(LOG_NONE, "Warning, prereserve of %p:0x%lx failed (%s)\n", my_wine_reserve[idx].addr, my_wine_reserve[idx].size, strerror(errno));
if(p!=(void*)-1)
munmap(p, my_wine_reserve[idx].size);
my_wine_reserve[idx].addr = NULL;
my_wine_reserve[idx].size = 0;
} else {
printf_log(LOG_DEBUG, "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);
return (void*)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(my_context, (uintptr_t)my_wine_reserve[i].addr, my_wine_reserve[i].size, 0); // prepare the prereserved area for exec, with linker
#endif
}
#endif
|