Name | Executed | Routines | % | Executed | Lines | % | Unexecuted |
/home/matt/eu/rds/include/std/machine.e | 10 | 20 | 50.00% | 87 | 149 | 58.39% | 62 |
Routine | Executed | Lines | Unexecuted | |
poke_string() | 0 | 11 | 0.00% | 11 |
poke_wstring() | 0 | 9 | 0.00% | 9 |
allocate_wstring() | 0 | 8 | 0.00% | 8 |
allocate_data() | 0 | 6 | 0.00% | 6 |
peek_wstring() | 0 | 6 | 0.00% | 6 |
allocate_protect() | 23 | 27 | 85.19% | 4 |
DEP_on() | 0 | 3 | 0.00% | 3 |
free() | 11 | 14 | 78.57% | 3 |
allocate_pointer_array() | 7 | 9 | 77.78% | 2 |
block_aligned() | 0 | 2 | 0.00% | 2 |
is_DEP_supported() | 0 | 2 | 0.00% | 2 |
is_using_DEP() | 0 | 2 | 0.00% | 2 |
page_aligned_address() | 0 | 2 | 0.00% | 2 |
allocate_string() | 7 | 8 | 87.50% | 1 |
allocate_string_pointer_array() | 6 | 7 | 85.71% | 1 |
allocate() | 7 | 7 | 100.00% | 0 |
allocate_code() | 2 | 2 | 100.00% | 0 |
free_pointer_array() | 10 | 10 | 100.00% | 0 |
std_library_address() | 4 | 4 | 100.00% | 0 |
valid_memory_protection_constant() | 2 | 2 | 100.00% | 0 |
# | Executed | |
1 | -- (c) Copyright - See License.txt | |
2 | -- | |
3 | namespace machine | |
4 | ||
5 | include std/dll.e | |
6 | include std/error.e | |
7 | public include std/memconst.e | |
8 | include std/types.e | |
9 | ||
10 | 101 | ifdef SAFE then |
11 | ||
12 | public include std/safe.e as memory | |
13 | ||
14 | elsedef | |
15 | ||
16 | public include std/memory.e as memory | |
17 | ||
18 | end ifdef | |
19 | ||
20 | integer FREE_ARRAY_RID | |
21 | ||
22 | 0 | |
23 | 0 | return remainder(a,4096)=0 |
24 | end type | |
25 | ||
26 | ||
27 | --**** | |
28 | -- === Memory allocation | |
29 | -- | |
30 | ||
31 | --** | |
32 | -- Allocate a contiguous block of data memory. | |
33 | -- | |
34 | -- Parameters: | |
35 | -- # ##n## : a positive integer, the size of the requested block. | |
36 | -- # ##cleanup## : an integer, if non-zero, then the returned pointer will be | |
37 | -- automatically freed when its reference count drops to zero, or | |
38 | -- when passed as a parameter to [[:delete]]. | |
39 | -- | |
40 | -- Return: | |
41 | -- An **atom**, the address of the allocated memory or 0 if the memory | |
42 | -- can't be allocated. | |
43 | -- | |
44 | -- Comments: | |
45 | -- Since ##allocate_string##() allocates memory, you are responsible to | |
46 | -- [[:free]]() the block when done with it if ##cleanup## is zero. | |
47 | -- If ##cleanup## is non-zero, then the memory can be freed by calling | |
48 | -- [[:delete]], or when the pointer's reference count drops to zero. | |
49 | -- When you are finished using the block, you should pass the address of the block to | |
50 | -- ##[[:free]]()## if ##cleanup## is zero. If ##cleanup## is non-zero, then the memory | |
51 | -- can be freed by calling [[:delete]], or when the pointer's reference count drops to zero. | |
52 | -- This will free the block and make the memory available for other purposes. When | |
53 | -- your program terminates, the operating system will reclaim all memory for use with other | |
54 | -- programs. An address returned by this function shouldn't be passed to ##[[:call]]()##. | |
55 | -- For that purpose you may use ##[[:allocate_code]]()## instead. | |
56 | -- | |
57 | -- The address returned will be at least 4-byte aligned. | |
58 | -- | |
59 | -- Example 1: | |
60 | -- | |
61 | -- buffer = allocate(100) | |
62 | -- for i = 0 to 99 do | |
63 | -- poke(buffer+i, 0) | |
64 | -- end for | |
65 | -- | |
66 | -- | |
67 | -- See Also: | |
68 | -- [[:free]], [[:peek]], [[:poke]], [[:mem_set]], [[:allocate_code]] | |
69 | ||
70 | 512 | |
71 | -- allocate memory block and add it to safe list | |
72 | machine_addr iaddr | |
73 | machine_addr eaddr | |
74 | 512 | ifdef DATA_EXECUTE then |
75 | -- high level call: No need to add BORDER_SPACE*2 here. | |
76 | eaddr = machine:allocate_protect( n, 1, PAGE_READ_WRITE_EXECUTE ) | |
77 | elsedef | |
78 | 512 | iaddr = eu:machine_func(M_ALLOC, n+BORDER_SPACE*2) |
79 | 512 | eaddr = prepare_block(iaddr, n, PAGE_READ_WRITE ) |
80 | end ifdef | |
81 | 512 | if cleanup then |
82 | 2 | eaddr = delete_routine( eaddr, FREE_RID ) |
83 | end if | |
84 | 512 | return eaddr |
85 | end function | |
86 | ||
87 | --** | |
88 | -- Allocate n bytes of memory and return the address. | |
89 | -- Free the memory using free() below. | |
90 | ||
91 | 0 | |
92 | -- allocate memory block and add it to safe list | |
93 | machine_addr a | |
94 | bordered_address sla | |
95 | 0 | a = eu:machine_func(M_ALLOC, n+BORDER_SPACE*2) |
96 | 0 | sla = prepare_block(a, n, PAGE_READ_WRITE ) |
97 | 0 | if cleanup then |
98 | 0 | return delete_routine( sla, FREE_RID ) |
99 | else | |
100 | 0 | return sla |
101 | end if | |
102 | end function | |
103 | ||
104 | ||
105 | --** | |
106 | -- Allocate a NULL terminated pointer array. | |
107 | -- | |
108 | -- Parameters: | |
109 | -- # ##pointers## : a sequence of pointers to add to the pointer array. | |
110 | -- # ##cleanup## : an integer, if non-zero, then the returned pointer will be | |
111 | -- automatically freed when its reference count drops to zero, or | |
112 | -- when passed as a parameter to [[:delete]] | |
113 | -- | |
114 | -- Comments: | |
115 | -- This function adds the NULL terminator. | |
116 | -- | |
117 | -- Example 1: | |
118 | -- | |
119 | -- atom pa = allocate_pointer_array({ allocate_string("1"), allocate_string("2") }) | |
120 | -- | |
121 | -- | |
122 | -- See Also: | |
123 | -- [[:allocate_string_pointer_array]], [[:free_pointer_array]] | |
124 | ||
125 | 2 | |
126 | atom pList | |
127 | ||
128 | 2 | if atom(pointers) then |
129 | 0 | return 0 |
130 | end if | |
131 | ||
132 | 2 | pointers &= 0 |
133 | 2 | pList = allocate(length(pointers) * 4) |
134 | 2 | poke4(pList, pointers) |
135 | 2 | if cleanup then |
136 | 0 | return delete_routine( pList, FREE_ARRAY_RID ) |
137 | end if | |
138 | 2 | return pList |
139 | end function | |
140 | ||
141 | --** | |
142 | -- Free a NULL terminated pointers array. | |
143 | -- | |
144 | -- Parameters: | |
145 | -- # ##pointers_array## : memory address of where the NULL terminated array exists at. | |
146 | -- | |
147 | -- Comments: | |
148 | -- This is for NULL terminated lists, such as allocated by [[:allocate_pointer_array]]. | |
149 | -- Do not call ##free_pointer_array##() for a pointer that was allocated to be cleaned | |
150 | -- up automatically. Instead, use [[:delete]]. | |
151 | -- | |
152 | -- See Also: | |
153 | -- [[:allocate_pointer_array]], [[:allocate_string_pointer_array]] | |
154 | ||
155 | 1 | |
156 | 1 | atom saved = pointers_array, |
157 | 1 | ptr = peek4u(pointers_array) |
158 | ||
159 | 1 | while ptr do |
160 | 2 | deallocate(ptr) |
161 | ||
162 | 2 | pointers_array+=4 |
163 | 2 | ptr = peek4u(pointers_array) |
164 | 2 | end while |
165 | ||
166 | 1 | free(saved) |
167 | 1 | end procedure |
168 | 101 | FREE_ARRAY_RID = routine_id("free_pointer_array") |
169 | ||
170 | --** | |
171 | -- Allocate a C-style null-terminated array of strings in memory | |
172 | -- | |
173 | -- Parameters: | |
174 | -- # ##string_list## : sequence of strings to store in RAM. | |
175 | -- # ##cleanup## : an integer, if non-zero, then the returned pointer will be | |
176 | -- automatically freed when its reference count drops to zero, or | |
177 | -- when passed as a parameter to [[:delete]] | |
178 | -- | |
179 | -- Returns: | |
180 | -- An **atom**, the address of the memory block where the string pointer | |
181 | -- array was stored. | |
182 | -- | |
183 | -- Example 1: | |
184 | -- | |
185 | -- atom p = allocate_string_pointer_array({ "One", "Two", "Three" }) | |
186 | -- -- Same as C: char *p = { "One", "Two", "Three", NULL }; | |
187 | -- | |
188 | -- | |
189 | -- See Also: | |
190 | -- [[:free_pointer_array]] | |
191 | ||
192 | 1 | |
193 | 1 | for i = 1 to length(string_list) do |
194 | 2 | string_list[i] = allocate_string(string_list[i]) |
195 | 2 | end for |
196 | ||
197 | 1 | if cleanup then |
198 | 0 | return delete_routine( allocate_pointer_array(string_list), FREE_ARRAY_RID ) |
199 | else | |
200 | 1 | return allocate_pointer_array(string_list) |
201 | end if | |
202 | end function | |
203 | ||
204 | ||
205 | --**** | |
206 | -- == Indirect Routine Calling | |
207 | -- | |
208 | -- < | |
209 | -- | |
210 | -- === SAFE mode | |
211 | -- | |
212 | -- During the development of your application, you can define the word ##SAFE## to cause | |
213 | -- ##machine.e## to use alternative memory functions. These functions are slower but | |
214 | -- help in the debugging stages. In general, ##SAFE## mode should not be enabled during | |
215 | -- production phases but only for development phases. | |
216 | -- | |
217 | -- To define the word ##SAFE## run your application with the ##-D SAFE## command line | |
218 | -- option, or add to the top of your main file ##with define SAFE##. | |
219 | -- | |
220 | -- | |
221 | -- === Data Execute mode | |
222 | -- | |
223 | -- ##Data Execute mode## makes data that will be returned from allocate() executable. On some | |
224 | -- systems allocate() will return memory that is not executable unless this mode has been enabled. | |
225 | -- When writing software you should use allocate_code() or allocate_protect() to get memory for | |
226 | -- execution. This is more efficient and more secure than using ##Data Execute mode##. However, | |
227 | -- since on many systems executing memory returned from allocate() will work much software will be | |
228 | -- written 4.0 and yet use allocate() for executable memory instead of the afore mentioned routines. | |
229 | -- Therefore, you may use this switch when you find that your are getting Data Execute Exceptions | |
230 | -- running some software. ##SAFE## mode will help you discover what memory should be changed to | |
231 | -- what access level. ##Data Execute## mode will only work when the EUPHORIA program uses | |
232 | -- std/machine.e not machine.e. | |
233 | ||
234 | -- To enable ##Data Execute mode## define the word ##DATA_EXECUTE## using | |
235 | -- the ##-D DATA_EXECUTE## command line option. | |
236 | -- | |
237 | ||
238 | --**** | |
239 | -- @[dyncall|] | |
240 | -- === Accessing Euphoria coded routines | |
241 | -- | |
242 | ||
243 | --**** | |
244 | -- Signature: | |
245 | -- | |
246 | -- | |
247 | -- Description: | |
248 | -- Return an integer id number for a user-defined Euphoria procedure or function. | |
249 | -- | |
250 | -- Parameters: | |
251 | -- # ##routine_name## : a string, the name of the procedure or function. | |
252 | -- | |
253 | -- Returns: | |
254 | -- An **integer**, known as a routine id, -1 if the named routine can't be found, else zero or more. | |
255 | -- | |
256 | -- Errors: | |
257 | -- ##routine_name## should not exceed 1,024 characters. | |
258 | -- | |
259 | -- Comments: | |
260 | -- The id number can be passed to [[:call_proc]]() or [[:call_func]](), to indirectly call | |
261 | -- the routine named by ##routine_name##. This id depends on the internal process of | |
262 | -- parsing your code, not on ##routine_name##. | |
263 | -- | |
264 | -- The routine named ##routine_name## must be visible, i.e. callable, at the place where | |
265 | -- ##routine_id##() is used to get the id number. If it is not, -1 is returned. | |
266 | -- | |
267 | -- Indirect calls to the routine can appear earlier in the program than the definition of the routine, | |
268 | -- but the id number can only be obtained in code that comes after the definition | |
269 | -- of the routine - see example 2 below. | |
270 | -- | |
271 | -- Once obtained, a valid routine id can be used at any place in the program to call | |
272 | -- a routine indirectly via [[:call_proc]]()/[[:call_func]](), including at places where | |
273 | -- the routine is no longer in scope. | |
274 | -- | |
275 | -- Some typical uses of ##routine_id##() are: | |
276 | -- | |
277 | -- # Creating a subroutine that takes another routine as a parameter. (See Example 2 below) | |
278 | -- # Using a sequence of routine id's to make a case (switch) statement. Using the | |
279 | -- [[:switch statement]] is more efficient. | |
280 | -- # Setting up an Object-Oriented system. | |
281 | -- # Getting a routine id so you can pass it to [[:call_back]](). (See [[:Platform-Specific Issues]]) | |
282 | -- # Getting a routine id so you can pass it to [[:task_create]](). (See [[:Multitasking in Euphoria]]) | |
283 | -- # Calling a routine that is defined later in a program. This is no longer needed from v4.0 onward. | |
284 | -- | |
285 | -- Note that C routines, callable by Euphoria, also have ids, but they cannot be used where | |
286 | -- routine ids are, because of the different type checking and other technical issues. | |
287 | -- See [[:define_c_proc]]() and [[:define_c_func]](). | |
288 | -- | |
289 | -- Example 1: | |
290 | -- | |
291 | -- procedure foo() | |
292 | -- puts(1, "Hello World\n") | |
293 | -- end procedure | |
294 | -- | |
295 | -- integer foo_num | |
296 | -- foo_num = routine_id("foo") | |
297 | -- | |
298 | -- call_proc(foo_num, {}) -- same as calling foo() | |
299 | -- | |
300 | -- | |
301 | -- Example 2: | |
302 | -- | |
303 | -- function apply_to_all(sequence s, integer f) | |
304 | -- -- apply a function to all elements of a sequence | |
305 | -- sequence result | |
306 | -- result = {} | |
307 | -- for i = 1 to length(s) do | |
308 | -- -- we can call add1() here although it comes later in the program | |
309 | -- result = append(result, call_func(f, {s[i]})) | |
310 | -- end for | |
311 | -- return result | |
312 | -- end function | |
313 | -- | |
314 | -- function add1(atom x) | |
315 | -- return x + 1 | |
316 | -- end function | |
317 | -- | |
318 | -- -- add1() is visible here, so we can ask for its routine id | |
319 | -- ? apply_to_all({1, 2, 3}, routine_id("add1")) | |
320 | -- -- displays {2,3,4} | |
321 | -- | |
322 | -- | |
323 | -- See Also: | |
324 | -- [[:call_proc]], [[:call_func]], [[:call_back]], [[:define_c_func]], [[:define_c_proc]], | |
325 | -- [[:task_create]], [[:Platform-Specific Issues]], [[:Indirect routine calling]] | |
326 | ||
327 | --**** | |
328 | -- Signature: | |
329 | -- | |
330 | -- | |
331 | -- Description: | |
332 | -- Call the user-defined Euphoria function by routine id. | |
333 | -- | |
334 | -- Parameters: | |
335 | -- # ##id## : an integer, the routine id of the function to call | |
336 | -- # ##args## : a sequence, the parameters to pass to the function. | |
337 | -- | |
338 | -- Returns: | |
339 | -- The **value**, the called function returns. | |
340 | -- | |
341 | -- Errors: | |
342 | -- If ##id## is negative or otherwise unknown, an error occurs. | |
343 | -- | |
344 | -- If the length of ##args## is not the number of parameters the function takes, an error occurs. | |
345 | -- | |
346 | -- Comments: | |
347 | -- ##id## must be a valid routine id returned by [[:routine_id]](). | |
348 | -- | |
349 | -- ##args## must be a sequence of argument values of length n, where n is the number of | |
350 | -- arguments required by the called function. Defaulted parameters currently cannot be | |
351 | -- synthesized while making a indirect call. | |
352 | -- | |
353 | -- If the function with id ##id## does not take any arguments then ##args## should be ##{}##. | |
354 | -- | |
355 | -- Example 1: | |
356 | -- Take a look at the sample program called ##demo/csort.ex## | |
357 | -- | |
358 | -- See Also: | |
359 | -- [[:call_proc]], [[:routine_id]], [[:c_func]] | |
360 | -- | |
361 | ||
362 | --**** | |
363 | -- Signature: | |
364 | -- | |
365 | -- | |
366 | -- Description: | |
367 | -- Call a user-defined Euphoria procedure by routine id. | |
368 | -- | |
369 | -- Parameters: | |
370 | -- # ##id## : an integer, the routine id of the procedure to call | |
371 | -- # ##args## : a sequence, the parameters to pass to the function. | |
372 | -- | |
373 | -- Errors: | |
374 | -- If ##id## is negative or otherwise unknown, an error occurs. | |
375 | -- | |
376 | -- If the length of ##args## is not the number of parameters the function takes, an error occurs. | |
377 | -- | |
378 | -- Comments: | |
379 | -- ##id## must be a valid routine id returned by [[:routine_id]](). | |
380 | -- | |
381 | -- ##args## must be a sequence of argument values of length n, where n is the number of | |
382 | -- arguments required by the called procedure. Defaulted parameters currently cannot be | |
383 | -- synthesized while making a indirect call. | |
384 | -- | |
385 | -- If the procedure with id ##id## does not take any arguments then ##args## should be ##{}##. | |
386 | -- | |
387 | -- Example 1: | |
388 | -- | |
389 | -- public integer foo_id | |
390 | -- | |
391 | -- procedure x() | |
392 | -- call_proc(foo_id, {1, "Hello World\n"}) | |
393 | -- end procedure | |
394 | -- | |
395 | -- procedure foo(integer a, sequence s) | |
396 | -- puts(a, s) | |
397 | -- end procedure | |
398 | -- | |
399 | -- foo_id = routine_id("foo") | |
400 | -- | |
401 | -- x() | |
402 | -- | |
403 | -- | |
404 | -- See Also: | |
405 | -- [[:call_func]], [[:routine_id]], [[:c_proc]] | |
406 | ||
407 | --**** | |
408 | -- === Accessing Euphoria internals | |
409 | ||
410 | --**** | |
411 | -- Signature: | |
412 | -- | |
413 | -- | |
414 | -- Description: | |
415 | -- Perform a machine-specific operation that returns a value. | |
416 | -- | |
417 | -- Returns: | |
418 | -- Depends on the called internal facility. | |
419 | -- | |
420 | -- Comments: | |
421 | -- This function us mainly used by the standard library files to implement machine dependent | |
422 | -- operations such as graphics and sound effects. This routine should normally be called | |
423 | -- indirectly via one of the library routines in a Euphoria include file. | |
424 | -- User programs normally do not need to call ##machine_func##. | |
425 | -- | |
426 | -- A direct call might cause a machine exception if done incorrectly. | |
427 | -- | |
428 | -- See Also: | |
429 | -- [[:machine_proc]] | |
430 | ||
431 | --**** | |
432 | -- Signature: | |
433 | -- | |
434 | -- | |
435 | -- Description: | |
436 | -- Perform a machine-specific operation that does not return a value. | |
437 | -- | |
438 | -- Comments: | |
439 | -- This procedure us mainly used by the standard library files to implement machine dependent | |
440 | -- operations such as graphics and sound effects. This routine should normally be called | |
441 | -- indirectly via one of the library routines in a Euphoria include file. | |
442 | -- User programs normally do not need to call ##machine_proc##. | |
443 | -- | |
444 | -- A direct call might cause a machine exception if done incorrectly. | |
445 | -- | |
446 | -- See Also: | |
447 | -- [[:machine_func]] | |
448 | ||
449 | ||
450 | 101 | ifdef WIN32 then |
451 | ||
452 | atom kernel_dll, memDLL_id, | |
453 | VirtualAlloc_rid, | |
454 | -- VirtualLock_rid, VirtualUnlock_rid, | |
455 | VirtualProtect_rid, GetLastError_rid, GetSystemInfo_rid | |
456 | ||
457 | memDLL_id = open_dll( "kernel32.dll" ) | |
458 | kernel_dll = memDLL_id | |
459 | VirtualAlloc_rid = define_c_func( memDLL_id, "VirtualAlloc", { C_POINTER, C_SIZE_T, C_DWORD, C_DWORD }, C_POINTER ) | |
460 | VirtualProtect_rid = define_c_func( memDLL_id, "VirtualProtect", { C_POINTER, C_SIZE_T, C_DWORD, C_POINTER }, C_BOOL ) | |
461 | VirtualFree_rid = define_c_func( kernel_dll, "VirtualFree", { C_POINTER, C_SIZE_T, C_DWORD }, C_BOOL ) | |
462 | -- VirtualLock_rid = define_c_func( memDLL_id, "VirtualLock", { C_POINTER, C_SIZE_T }, C_BOOL ) | |
463 | -- VirtualUnlock_rid = define_c_func( memDLL_id, "VirtualUnlock", { C_POINTER, C_SIZE_T }, C_BOOL ) | |
464 | GetLastError_rid = define_c_func( kernel_dll, "GetLastError", {}, C_DWORD ) | |
465 | GetSystemInfo_rid = define_c_proc( kernel_dll, "GetSystemInfo", { C_POINTER } ) | |
466 | if VirtualAlloc_rid != -1 and VirtualProtect_rid != -1 | |
467 | and GetLastError_rid != -1 and GetSystemInfo_rid != -1 | |
468 | then | |
469 | atom vaa = VirtualAlloc( 0, 1, or_bits( MEM_RESERVE, MEM_COMMIT ), PAGE_READ_WRITE_EXECUTE ) != 0 | |
470 | if vaa then | |
471 | DEP_really_works = 1 | |
472 | c_func( VirtualFree_rid, { vaa, 1, MEM_RELEASE } ) | |
473 | vaa = 0 | |
474 | end if | |
475 | end if | |
476 | ||
477 | integer page_size = 0 | |
478 | if GetSystemInfo_rid != -1 then | |
479 | bordered_address system_info_ptr = allocate( 9 * 4 ) | |
480 | if system_info_ptr != 0 then | |
481 | c_proc( GetSystemInfo_rid, { system_info_ptr } ) | |
482 | page_size = peek4u( system_info_ptr + 4 ) | |
483 | free( system_info_ptr ) | |
484 | end if | |
485 | end if | |
486 | public constant PAGE_SIZE = page_size | |
487 | elsifdef UNIX then | |
488 | 101 | constant getpagesize_rid = define_c_func( -1, "getpagesize", { }, C_UINT ) |
489 | 101 | public constant PAGE_SIZE = c_func( getpagesize_rid, {} ) |
490 | end ifdef | |
491 | ||
492 | 101 | ifdef WIN32 then |
493 | function VirtualAlloc( atom addr, atom size, atom allocation_type, atom protect_ ) | |
494 | atom r1 | |
495 | r1 = c_func( VirtualAlloc_rid, {addr, size, allocation_type, protect_ } ) | |
496 | return r1 | |
497 | end function | |
498 | end ifdef | |
499 | ||
500 | --**** | |
501 | -- == Types supporting Memory | |
502 | ||
503 | --** | |
504 | -- protection constants type | |
505 | 60 | |
506 | 60 | return 0 != find( x, MEMORY_PROTECTION ) |
507 | end type | |
508 | ||
509 | --** | |
510 | -- page aligned address type | |
511 | 0 | |
512 | 0 | return remainder( a, PAGE_SIZE ) = 0 |
513 | end type | |
514 | ||
515 | 0 | |
516 | 0 | return DEP_really_works |
517 | end function | |
518 | ||
519 | 0 | |
520 | 0 | return use_DEP |
521 | end function | |
522 | ||
523 | 0 | |
524 | 0 | use_DEP = value |
525 | 0 | end procedure |
526 | ||
527 | --**** | |
528 | -- === Allocating and Writing to memory: | |
529 | ||
530 | --** | |
531 | -- Allocates and copies data into executable memory. | |
532 | -- | |
533 | -- Parameters: | |
534 | -- # ##a_sequence_of_machine_code## : is the machine code to | |
535 | -- be put into memory to be later called with [[:call()]] | |
536 | -- # the ##word length## : of the said code. You can specify your | |
537 | -- code as 1-byte, 2-byte or 4-byte chunks if you wish. If your machine code is byte | |
538 | -- code specify 1. The default is 1. | |
539 | -- | |
540 | -- Return Value: | |
541 | -- An **address**, | |
542 | -- The function returns the address in memory of the code, that can be | |
543 | -- safely executed whether DEP is enabled or not or 0 if it fails. On the | |
544 | -- other hand, if you try to execute a code address returned by [[:allocate()]] | |
545 | -- with DEP enabled the program will receive a machine exception. | |
546 | -- | |
547 | -- Comments: | |
548 | -- | |
549 | -- Use this for the machine code you want to run in memory. The copying is | |
550 | -- done for you and when the routine returns the memory may not be readable | |
551 | -- or writeable but it is guaranteed to be executable. If you want to also | |
552 | -- write to this memory **after the machine code has been copied** you should | |
553 | -- use [[:allocate_protect()]] instead and you should read about having memory | |
554 | -- executable and writeable at the same time is a bad idea. You mustn't use | |
555 | -- ##free()## on memory returned from this function. You may instead | |
556 | -- use ##free_code()## but since you will probably need the code throughout | |
557 | -- the life of your program's process this normally is not necessary. | |
558 | -- If you want to put only data in the memory to be read and written use [[:allocate]]. | |
559 | -- See Also: | |
560 | -- [[:allocate]], [[:free_code]], [[:allocate_protect]] | |
561 | ||
562 | 1 | |
563 | ||
564 | 1 | return allocate_protect( data, wordsize, PAGE_EXECUTE ) |
565 | ||
566 | end function | |
567 | ||
568 | ||
569 | ||
570 | --** | |
571 | -- Type for memory addresses | |
572 | -- | |
573 | -- an address returned from allocate() or allocate_protect() | |
574 | -- or allocate_code() or the value 0. | |
575 | -- | |
576 | -- Return Value: | |
577 | -- An **integer**, | |
578 | -- The type will return 1 if the parameter was returned | |
579 | -- from one of these functions (and has not yet been freeed) | |
580 | -- | |
581 | -- Comments: | |
582 | -- This type is equivalent to atom unless SAFE is defined. | |
583 | -- Only values that satisfy this type may be passed into | |
584 | -- free or free_code. | |
585 | -- | |
586 | 28 | |
587 | 28 | ifdef not SAFE then |
588 | 10 | return 1 |
589 | elsedef | |
590 | 18 | return (addr = 0) or bordered_address(addr) |
591 | end ifdef | |
592 | end type | |
593 | ||
594 | 101 | ifdef WIN32 then |
595 | std_library_address oldprotptr = allocate_data(4) | |
596 | end ifdef | |
597 | ||
598 | --** | |
599 | -- Allocates and copies data into memory and gives it protection using | |
600 | -- [[:Standard Library Memory Protection Constants]] or | |
601 | -- [[:Microsoft Windows Memory Protection Constants]]. The user may only pass in one of these | |
602 | -- constants. If you only wish to execute a sequence as machine code use ##allocate_code()##. | |
603 | -- If you only want to read and write data into memory use ##allocate()##. | |
604 | -- | |
605 | -- See [[http://msdn.microsoft.com/en-us/library/aa366786(VS.85).aspx "MSDN: Microsoft's Memory Protection Constants"]] | |
606 | -- | |
607 | -- Parameters: | |
608 | -- # ##data## : is the machine code to be put into memory. | |
609 | -- # ##wordsize## : is the size each element of data will take in | |
610 | -- memory. Are they 1-byte, 2-bytes or 4-bytes long? Specify here. The default is 1. | |
611 | -- # ##protection## : is the particular Windows protection. | |
612 | -- | |
613 | -- Returns: | |
614 | -- An **address**, | |
615 | -- The function returns the address to the required memory | |
616 | -- or 0 if it fails. This function is guaranteed to return memory on | |
617 | -- the 4 byte boundary. It also guarantees that the memory returned with | |
618 | -- at least the protection given (but you may get more). | |
619 | -- | |
620 | -- If you want to call ##allocate_protect( data, PAGE_READWRITE )##, you can use | |
621 | -- [[:allocate]] instead. It is more efficient and simpler. | |
622 | -- | |
623 | -- If you want to call ##allocate_protect( data, PAGE_EXECUTE )##, you can use | |
624 | -- [[:allocate_code()]] instead. It is simpler. | |
625 | -- | |
626 | -- You mustn't use [[:free()]] on memory returned from this function, instead use [[:free_code()]]. | |
627 | ||
628 | 18 | |
629 | -- set the actual protection for the OS to /true_protection/ in all cases | |
630 | -- /protection/ is put into the checking system if it is there using SAFE | |
631 | ||
632 | 18 | atom iaddr = 0 |
633 | std_library_address eaddr | |
634 | integer size | |
635 | valid_memory_protection_constant first_protection | |
636 | ||
637 | 18 | valid_memory_protection_constant true_protection = protection |
638 | ||
639 | -- when SAFE is defined /true_protection/ always allows READ so that block edges can be | |
640 | -- checked and WRITE so that we can add leader and trailer markers in this routine. | |
641 | -- when SAFE is not defined /true_protection/ is set to what is passed in without | |
642 | -- modification. | |
643 | 18 | ifdef SAFE then |
644 | 8 | if ( (not test_write(protection)) or (not test_read(protection) ) ) then |
645 | 6 | if test_exec(protection) then |
646 | 1 | true_protection = PAGE_READ_WRITE_EXECUTE |
647 | else | |
648 | 5 | true_protection = PAGE_READ_WRITE |
649 | end if | |
650 | end if | |
651 | end ifdef | |
652 | ||
653 | 18 | if atom(data) then |
654 | 3 | size = data * wordsize |
655 | 3 | first_protection = true_protection |
656 | else | |
657 | 15 | size = length(data) * wordsize |
658 | 15 | first_protection = PAGE_READ_WRITE |
659 | end if | |
660 | ||
661 | 18 | ifdef WIN32 then |
662 | if dep_works() then | |
663 | iaddr = eu:c_func(VirtualAlloc_rid, | |
664 | { 0, size+BORDER_SPACE*2, or_bits( MEM_RESERVE, MEM_COMMIT ), first_protection }) | |
665 | else | |
666 | iaddr = machine_func(M_ALLOC, size+BORDER_SPACE*2) | |
667 | end if | |
668 | elsedef | |
669 | 18 | iaddr = machine_func(M_ALLOC, size+BORDER_SPACE*2) |
670 | end ifdef | |
671 | 18 | if iaddr = 0 then |
672 | 0 | return 0 |
673 | end if | |
674 | ||
675 | -- eaddr is set here | |
676 | 18 | eaddr = prepare_block( iaddr, size, protection ) |
677 | ||
678 | 18 | if eaddr = 0 or atom( data ) then |
679 | 3 | return eaddr |
680 | end if | |
681 | ||
682 | 15 | switch wordsize do |
683 | case 1 then | |
684 | 15 | eu:poke( eaddr, data ) |
685 | ||
686 | case 2 then | |
687 | 0 | eu:poke2( eaddr, data ) |
688 | ||
689 | case 4 then | |
690 | 0 | eu:poke4( eaddr, data ) |
691 | ||
692 | case else | |
693 | 0 | crash("logic error: Wrong word size %d in allocate_protect", wordsize) |
694 | ||
695 | end switch | |
696 | ||
697 | ||
698 | 15 | ifdef WIN32 then |
699 | ifdef SAFE then | |
700 | -- here we can take away write access | |
701 | -- from true_protection if protection doesn't have it. | |
702 | -- true_protection must have read access though. | |
703 | switch protection do | |
704 | case PAGE_EXECUTE then | |
705 | true_protection = PAGE_EXECUTE_READ | |
706 | ||
707 | case PAGE_EXECUTE_WRITECOPY then | |
708 | true_protection = PAGE_EXECUTE_READWRITE | |
709 | ||
710 | case PAGE_WRITECOPY, PAGE_NOACCESS then | |
711 | true_protection = PAGE_READONLY | |
712 | ||
713 | case else | |
714 | true_protection = protection | |
715 | end switch | |
716 | end ifdef | |
717 | if dep_works() then | |
718 | if eu:c_func( VirtualProtect_rid, { iaddr, size, true_protection , oldprotptr } ) = 0 then | |
719 | -- 0 indicates failure here | |
720 | c_func(VirtualFree_rid, { iaddr, size, MEM_RELEASE }) | |
721 | return 0 | |
722 | end if | |
723 | end if | |
724 | end ifdef | |
725 | ||
726 | 15 | return eaddr |
727 | end function | |
728 | ||
729 | ||
730 | ||
731 | --** | |
732 | -- Stores a C-style null-terminated ANSI string in memory | |
733 | -- | |
734 | -- Parameters: | |
735 | -- # ##buffaddr##: an atom, the RAM address to to the string at. | |
736 | -- # ##buffsize##: an integer, the number of bytes available, starting from ##buffaddr##. | |
737 | -- # ##s## : a sequence, the string to store at address ##buffaddr##. | |
738 | -- | |
739 | -- Comments: | |
740 | -- * This does not allocate an RAM. You must supply the preallocated area. | |
741 | -- * This can only be used on ANSI strings. It cannot be used for double-byte strings. | |
742 | -- * If ##s## is not a string, nothing is stored and a zero is returned. | |
743 | -- | |
744 | -- Returns: | |
745 | -- An atom. If this is zero, then nothing was stored, otherwise it is the | |
746 | -- address of the first byte after the stored string. | |
747 | -- | |
748 | -- Example 1: | |
749 | -- | |
750 | -- atom title | |
751 | -- | |
752 | -- title = allocate(1000) | |
753 | -- if poke_string(title, 1000, "The Wizard of Oz") then | |
754 | -- -- successful | |
755 | -- else | |
756 | -- -- failed | |
757 | -- end if | |
758 | -- | |
759 | -- | |
760 | -- See Also: | |
761 | -- [[:allocate]], [[:allocate_string]] | |
762 | ||
763 | 0 | |
764 | ||
765 | 0 | if buffaddr <= 0 then |
766 | 0 | return 0 |
767 | end if | |
768 | ||
769 | 0 | if not string(s) then |
770 | 0 | return 0 |
771 | end if | |
772 | ||
773 | 0 | if buffsize <= length(s) then |
774 | 0 | return 0 |
775 | end if | |
776 | ||
777 | 0 | poke(buffaddr, s) |
778 | 0 | buffaddr += length(s) |
779 | 0 | poke(buffaddr, 0) |
780 | ||
781 | 0 | return buffaddr |
782 | end function | |
783 | ||
784 | --** | |
785 | -- Stores a C-style null-terminated Double-Byte string in memory | |
786 | -- | |
787 | -- Parameters: | |
788 | -- # ##buffaddr##: an atom, the RAM address to to the string at. | |
789 | -- # ##buffsize##: an integer, the number of bytes available, starting from ##buffaddr##. | |
790 | -- # ##s## : a sequence, the string to store at address ##buffaddr##. | |
791 | -- | |
792 | -- Comments: | |
793 | -- * This does not allocate an RAM. You must supply the preallocated area. | |
794 | -- * This uses two bytes per string character. **Note** that ##buffsize## | |
795 | -- is the number of //bytes// available in the buffer and not the number | |
796 | -- of //characters// available. | |
797 | -- * If ##s## is not a double-byte string, nothing is stored and a zero is returned. | |
798 | -- | |
799 | -- Returns: | |
800 | -- An atom. If this is zero, then nothing was stored, otherwise it is the | |
801 | -- address of the first byte after the stored string. | |
802 | -- | |
803 | -- Example 1: | |
804 | -- | |
805 | -- atom title | |
806 | -- | |
807 | -- title = allocate(1000) | |
808 | -- if poke_wstring(title, 1000, "The Wizard of Oz") then | |
809 | -- -- successful | |
810 | -- else | |
811 | -- -- failed | |
812 | -- end if | |
813 | -- | |
814 | -- | |
815 | -- See Also: | |
816 | -- [[:allocate]], [[:allocate_wstring]] | |
817 | ||
818 | 0 | |
819 | ||
820 | 0 | if buffaddr <= 0 then |
821 | 0 | return 0 |
822 | end if | |
823 | ||
824 | 0 | if buffsize <= 2 * length(s) then |
825 | 0 | return 0 |
826 | end if | |
827 | ||
828 | 0 | poke2(buffaddr, s) |
829 | 0 | buffaddr += 2 * length(s) |
830 | 0 | poke2(buffaddr, 0) |
831 | ||
832 | 0 | return buffaddr |
833 | end function | |
834 | ||
835 | --** | |
836 | -- Allocate a C-style null-terminated string in memory | |
837 | -- | |
838 | -- Parameters: | |
839 | -- # ##s## : a sequence, the string to store in RAM. | |
840 | -- # ##cleanup## : an integer, if non-zero, then the returned pointer will be | |
841 | -- automatically freed when its reference count drops to zero, or | |
842 | -- when passed as a parameter to [[:delete]]. | |
843 | -- | |
844 | -- Returns: | |
845 | -- An **atom**, the address of the memory block where the string was | |
846 | -- stored, or 0 on failure. | |
847 | -- | |
848 | -- Comments: | |
849 | -- Only the 8 lowest bits of each atom in ##s## is stored. Use | |
850 | -- ##allocate_wstring##() for storing double byte encoded strings. | |
851 | -- | |
852 | -- There is no allocate_string_low() function. However, you could easily | |
853 | -- craft one by adapting the code for ##allocate_string##. | |
854 | -- | |
855 | -- Since ##allocate_string##() allocates memory, you are responsible to | |
856 | -- [[:free]]() the block when done with it if ##cleanup## is zero. | |
857 | -- If ##cleanup## is non-zero, then the memory can be freed by calling | |
858 | -- [[:delete]], or when the pointer's reference count drops to zero. | |
859 | -- | |
860 | -- Example 1: | |
861 | -- | |
862 | -- atom title | |
863 | -- | |
864 | -- title = allocate_string("The Wizard of Oz") | |
865 | -- | |
866 | -- | |
867 | -- See Also: | |
868 | -- [[:allocate]], [[:allocate_wstring]] | |
869 | ||
870 | 169 | |
871 | atom mem | |
872 | ||
873 | 169 | mem = allocate( length(s) + 1) -- Thanks to Igor |
874 | ||
875 | 169 | if mem then |
876 | 169 | poke(mem, s) |
877 | 169 | poke(mem+length(s), 0) -- Thanks to Aku |
878 | 169 | if cleanup then |
879 | 0 | mem = delete_routine( mem, FREE_RID ) |
880 | end if | |
881 | end if | |
882 | ||
883 | 169 | return mem |
884 | end function | |
885 | ||
886 | --** | |
887 | -- Create a C-style null-terminated wchar_t string in memory | |
888 | -- | |
889 | -- Parameters: | |
890 | -- # ##s## : a unicode (utf16) string | |
891 | -- | |
892 | -- Returns: | |
893 | -- An **atom**, the address of the allocated string, or 0 on failure. | |
894 | -- | |
895 | -- See Also: | |
896 | -- [[:allocate_string]] | |
897 | -- | |
898 | 0 | |
899 | atom mem | |
900 | ||
901 | 0 | mem = allocate( 2 * (length(s) + 1) ) |
902 | 0 | if mem then |
903 | 0 | poke2(mem, s) |
904 | 0 | poke2(mem + length(s)*2, 0) |
905 | 0 | if cleanup then |
906 | 0 | mem = delete_routine( mem, FREE_RID ) |
907 | end if | |
908 | end if | |
909 | ||
910 | 0 | return mem |
911 | end function | |
912 | ||
913 | --** | |
914 | -- Return a unicode (utf16) string that are stored at machine address a. | |
915 | -- | |
916 | -- Parameters: | |
917 | -- # ##addr## : an atom, the address of the string in memory | |
918 | -- | |
919 | -- Returns: | |
920 | -- The **string**, at the memory position. The terminator is the null word (two bytes equal to 0). | |
921 | -- | |
922 | -- See Also: | |
923 | -- [[:peek_string]] | |
924 | ||
925 | 0 | |
926 | 0 | atom ptr = addr |
927 | ||
928 | 0 | while peek2u(ptr) do |
929 | 0 | ptr += 2 |
930 | 0 | end while |
931 | ||
932 | 0 | return peek2u({addr, (ptr - addr) / 2}) |
933 | end function | |
934 | ||
935 | --**** | |
936 | -- === Memory disposal | |
937 | -- | |
938 | ||
939 | --** | |
940 | -- Free up a previously allocated block of memory. | |
941 | -- @[machine:free] | |
942 | -- | |
943 | -- Parameters: | |
944 | -- # ##addr##, either a single atom or a sequence of atoms; these are addresses of a blocks to free. | |
945 | -- | |
946 | -- Comments: | |
947 | -- * Use ##free##() to return blocks of memory the during execution. This will reduce the chance of | |
948 | -- running out of memory or getting into excessive virtual memory swapping to disk. | |
949 | -- * Do not reference a block of memory that has been freed. | |
950 | -- * When your program terminates, all allocated memory will be returned to the system. | |
951 | -- * ##addr## must have been allocated previously using [[:allocate]](). You | |
952 | -- cannot use it to relinquish part of a block. Instead, you have to allocate | |
953 | -- a block of the new size, copy useful contents from old block there and | |
954 | -- then ##free##() the old block. | |
955 | -- * If the memory was allocated and automatic cleanup | |
956 | -- was specified, then do not call ##free()## directly. Instead, use [[:delete]]. | |
957 | -- * An ##addr## of zero is simply ignored. | |
958 | -- | |
959 | -- Example 1: | |
960 | -- ##demo/callmach.ex## | |
961 | -- | |
962 | -- See Also: | |
963 | -- [[:allocate]], [[:free_code]] | |
964 | 187 | |
965 | 187 | if number_array (addr) then |
966 | 12 | if ascii_string(addr) then |
967 | 0 | crash("free(\"%s\") is not a valid address", {addr}) |
968 | end if | |
969 | ||
970 | 12 | for i = 1 to length(addr) do |
971 | 24 | deallocate(addr[i]) |
972 | 24 | end for |
973 | 12 | return |
974 | 175 | elsif sequence(addr) then |
975 | 0 | crash("free() called with nested sequence") |
976 | end if | |
977 | ||
978 | 175 | if addr = 0 then |
979 | -- Special case, a zero address is assumed to be an uninitialized pointer, | |
980 | -- so it is ignored. | |
981 | 0 | return |
982 | end if | |
983 | ||
984 | 175 | deallocate(addr) |
985 | 172 | end procedure |
986 | 101 | FREE_RID = routine_id("free") |
987 | ||
988 | ||
989 | --**** | |
990 | -- Signature: | |
991 | -- include std/machine.e | |
992 | -- public procedure free_code( atom addr, integer size, valid_wordsize wordsize = 1 ) | |
993 | -- | |
994 | -- Description: | |
995 | -- Frees up allocated code memory | |
996 | -- | |
997 | -- Parameters: | |
998 | -- # ##addr## : must be an address returned by [[:allocate_code()]] or [[:allocate_protect()]]. Do **not** pass memory returned from [[:allocate()]] here! | |
999 | -- # ##size## : is the length of the sequence passed to ##alllocate_code()## or the size you specified when you called allocate_protect(). | |
1000 | -- # ##wordsize##: valid_wordsize default = 1 | |
1001 | -- | |
1002 | -- Comments: | |
1003 | -- Chances are you will not need to call this function because code allocations are typically public scope operations that you want to have available until your process exits. | |
1004 | -- | |
1005 | -- See Also: [[:allocate_code]], [[:free]] |