1 // vm_mgr.cpp : Defines the exported functions for the DLL application.
2 //
3
4 #include "stdafx.h"
5
6 #include <Windows.h>
7 #include <vector>
8 #include <assert.h>
9 #include <tchar.h>
10 #include "../common/assist.h"
11 #include"../error_no/error_no.h"
12 #include "../Log/log.h"
13 #include "vm_mgr.h"
14
15 #define VM_ADDR_GEN(addr, index) (assert(index < 16), (((index & 0xfULL) << 60) | addr))
16 #define VM_START_ADDR 0x100000000ULL
17 #define VM_WINDOW_SIZE (64 * 1024 * 1024UL)
18 #define VM_ALIGN_SIZE (64 * 1024)
19
20 struct vm_window {
21 void *p;
22 vm_ptr_t start;
23 unsigned long size;
24 };
25
26 struct vm_item {
27 int addr_index;
28 HANDLE mutext;
29 HANDLE hMap;
30 vm_ptr_t vm_start_ptr;
31 unsigned long long vm_size;
32 struct vm_window window;
33 TCHAR file_path[MAX_PATH];
34 };
35
36 struct {
37 std::vector<struct vm_item> tbl;
38 } vm;
39
40 static int find_empty_index()
41 {
42 int addr_index;
43 int i;
44
45 for (addr_index = 0; ; addr_index++) {
46 for (i = 0; i < vm.tbl.size(); i++) {
47 if (vm.tbl.at(i).addr_index == addr_index)
48 break;
49 }
50 assert(addr_index <= 16);
51 if (i >= vm.tbl.size())
52 return addr_index;
53 }
54 }
55
56 vm_ptr_t vm_alloc(unsigned long long size)
57 {
58 TCHAR tmp_path[MAX_PATH];
59 TCHAR tmp_file_path[MAX_PATH];
60 int err;
61 struct vm_item vm_item;
62
63 GetTempPath(ARRAY_SIZE(tmp_path), tmp_path);
64 GetTempFileName(tmp_path, _T("DediProg"), 0, tmp_file_path);
65
66 HANDLE hFile = CreateFile(
67 tmp_file_path,
68 GENERIC_READ | GENERIC_WRITE,
69 FILE_SHARE_READ | FILE_SHARE_WRITE,
70 NULL,
71 OPEN_ALWAYS,
72 FILE_FLAG_SEQUENTIAL_SCAN,
73 NULL
74 );
75 if (hFile == NULL) {
76 return NULL;
77 }
78
79 vm_item.hMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, size >> 32, size & 0xffffffff, NULL);
80 if (vm_item.hMap == NULL) {
81 err = GetLastError();
82 return -E_ALLOC_MEMORY_FAIL;
83 }
84 vm_item.vm_start_ptr = (vm_ptr_t)MapViewOfFile(
85 vm_item.hMap,
86 FILE_MAP_ALL_ACCESS,
87 0 >> 32,
88 0 & 0xffffffff,
89 min(size, VM_WINDOW_SIZE)
90 );
91
92 vm_item.addr_index = find_empty_index();
93 vm_item.vm_start_ptr = VM_ADDR_GEN(vm_item.vm_start_ptr, vm_item.addr_index);
94
95 assert(vm_item.vm_start_ptr < ((-1) >> 4));
96
97 CloseHandle(hFile);
98 hFile = NULL;
99 vm_item.vm_size = size;
100 vm_item.window.size = (unsigned long)min(VM_WINDOW_SIZE, size);
101 vm_item.window.start = vm_item.vm_start_ptr;
102 vm_item.window.p = (unsigned char *)vm_item.vm_start_ptr;
103 vm_item.mutext = CreateMutex(NULL, FALSE, NULL);
104 _tcsncpy(vm_item.file_path, tmp_file_path, ARRAY_SIZE(vm_item.file_path));
105 vm.tbl.push_back(vm_item);
106
107 return vm_item.vm_start_ptr;
108 }
109
110 static __inline int in_region(vm_ptr_t ptr, unsigned long long size)
111 {
112 //static int dbg = 0;
113 int i;
114
115 for (i = 0; i < (int)vm.tbl.size(); i++) {
116 if ((ptr + size) <= (vm.tbl.at(i).vm_start_ptr + vm.tbl.at(i).vm_size) && (ptr >= vm.tbl.at(i).vm_start_ptr))
117 return i;
118 //if (ptr + size > vm.tbl.at(i).vm_start_ptr + vm.tbl.at(i).vm_size)
119 // i = 'DEAD';
120 //if (ptr < vm.tbl.at(i).vm_start_ptr)
121 // i = 'INVA';
122 }
123
124 LOG_BEGIN {
125 log_add("----------------------------------------------");
126 log_add("| Virtual Memory layout |");
127 log_add("|--------------------------------------------|");
128 for (i = 0; i < (int)vm.tbl.size(); i++)
129 log_add("|window.start_addr:%llx | window.size:%llx |", vm.tbl.at(i).window.start, vm.tbl.at(i).window.size);
130 log_add("|--------------------------------------------|");
131 log_add("|user.ptr:%llx | user.size:%llx |", ptr, size);
132 log_add("----------------------------------------------");
133 } LOG_END;
134 //dbg++;
135 assert(!"Invalid Memory");
136 return -1;
137 }
138
139 static __inline unsigned char *scroll_window(int vm_index, vm_ptr_t ptr, unsigned long size)
140 {
141 unsigned char *p;
142 vm_ptr_t win_start;
143 unsigned long win_size;
144 unsigned long long file_offset;
145 unsigned long long tmp_offset;
146
147
148 win_start = vm.tbl.at(vm_index).window.start;
149 win_size = vm.tbl.at(vm_index).window.size;
150
151
152 UnmapViewOfFile(vm.tbl.at(vm_index).window.p);
153
154 win_size = (unsigned long)min(VM_WINDOW_SIZE, size);
155
156 assert(ptr >= vm.tbl.at(vm_index).vm_start_ptr);
157 file_offset = ptr - vm.tbl.at(vm_index).vm_start_ptr;
158
159 tmp_offset = file_offset / VM_ALIGN_SIZE * VM_ALIGN_SIZE;
160 tmp_offset = file_offset - tmp_offset;
161
162 file_offset = file_offset / VM_ALIGN_SIZE * VM_ALIGN_SIZE;
163
164 size += (unsigned long)tmp_offset;
165
166 p = (unsigned char *)MapViewOfFile(
167 vm.tbl.at(vm_index).hMap,
168 FILE_MAP_ALL_ACCESS,
169 file_offset >> 32,
170 file_offset & 0xffffffff,
171 size
172 );
173
174 if (p) {
175 vm.tbl.at(vm_index).window.start = ptr;
176 vm.tbl.at(vm_index).window.size = size;
177 vm.tbl.at(vm_index).window.p = p;
178
179 return p + tmp_offset;
180 }
181
182 return NULL;
183 }
184
185 int vm_write(vm_ptr_t pointer, const unsigned char *buff, unsigned long long size)
186 {
187 int ret;
188 unsigned char *p;
189 unsigned long len;
190 int index = in_region(pointer, size);
191
192 ret = 0;
193
194 if (index == -1) {
195 ret = -1;
196 goto end;
197 }
198 WaitForSingleObject(vm.tbl.at(index).mutext, 20000); /* timeout 10s */
199 while (size) {
200 len = (unsigned long)min(size, VM_WINDOW_SIZE);
201 p = scroll_window(index, pointer, len);
202 if (!p) {
203 ret = -1;
204 goto end;
205 }
206
207 memcpy(p, buff, len);
208
209 pointer += len;
210 buff += len;
211 size -= len;
212 }
213 end:
214 ReleaseMutex(vm.tbl.at(index).mutext);
215 return ret;
216 }
217
218
219 int vm_read(unsigned char *buff, vm_ptr_t ptr, unsigned long long size)
220 {
221 unsigned char *p;
222 unsigned long len;
223 int index;
224
225 assert(buff);
226
227 index = in_region(ptr, size);
228
229 if (index == -1)
230 return -E_ALLOC_MEMORY_FAIL;
231
232 while (size) {
233 len = (unsigned long)min(size, VM_WINDOW_SIZE);
234 p = scroll_window(index, ptr, len);
235 if (!p)
236 return -1;
237
238 memcpy(buff, p, len);
239
240 ptr += len;
241 buff += len;
242 size -= len;
243 }
244
245 return 0;
246 }
247
248 int vm_free(vm_ptr_t ptr)
249 {
250 int i;
251
252 LOG_BEGIN {
253 log_add("----------------------------------------------");
254 log_add("| Virtual Memory layout |");
255 log_add("|--------------------------------------------|");
256 for (i = 0; i < (int)vm.tbl.size(); i++)
257 log_add("|window.start_addr:%llx | window.size:%llx |", vm.tbl.at(i).window.start, vm.tbl.at(i).window.size);
258 log_add("----------------------------------------------");
259 } LOG_END;
260
261 for (i = 0; i < (int)vm.tbl.size(); i++) {
262 if (vm.tbl.at(i).vm_start_ptr == ptr) {
263 assert(vm.tbl.at(i).hMap);
264
265 UnmapViewOfFile(vm.tbl.at(i).window.p);
266 CloseHandle(vm.tbl.at(i).hMap);
267
268 DeleteFile(vm.tbl.at(i).file_path);
269
270 vm.tbl.erase(vm.tbl.begin() + i);
271 return 0;
272 }
273 }
274
275 assert(!"Invalid pointer");
276
277 return 0;
278 }