12 #define USE_DL_PREFIX 1
14 #include "mono-codeman.h"
15 #include "mono-mmap.h"
16 #include "mono-counters.h"
18 #include <mono/metadata/class-internals.h>
19 #include <mono/metadata/profiler-private.h>
20 #ifdef HAVE_VALGRIND_MEMCHECK_H
21 #include <valgrind/memcheck.h>
24 #if defined(__native_client_codegen__) && defined(__native_client__)
26 #include <nacl/nacl_dyncode.h>
29 static uintptr_t code_memory_used = 0;
32 * AMD64 processors maintain icache coherency only for pages which are
33 * marked executable. Also, windows DEP requires us to obtain executable memory from
34 * malloc when using dynamic code managers. The system malloc can't do this so we use a
35 * slighly modified version of Doug Lea's Malloc package for this purpose:
36 * http://g.oswego.edu/dl/html/malloc.html
41 #if defined(__ia64__) || defined(__x86_64__)
43 * We require 16 byte alignment on amd64 so the fp literals embedded in the code are
44 * properly aligned for SSE2.
50 #ifdef __native_client_codegen__
51 /* For Google Native Client, all targets of indirect control flow need to */
52 /* be aligned to a 32-byte boundary. MIN_ALIGN was updated to 32 to force */
53 /* alignment for calls from tramp-x86.c to mono_global_codeman_reserve() */
54 /* and mono_domain_code_reserve(). */
59 /* if a chunk has less than this amount of free space it's considered full */
60 #define MAX_WASTAGE 32
64 #define ARCH_MAP_FLAGS MONO_MMAP_32BIT
66 #define ARCH_MAP_FLAGS 0
69 #define MONO_PROT_RWX (MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_EXEC)
71 typedef struct _CodeChunck CodeChunk;
83 unsigned int flags: 8;
84 /* this number of bytes is available to resolve addresses far in memory */
85 unsigned int bsize: 24;
88 struct _MonoCodeManager {
93 #if defined(__native_client_codegen__) && defined(__native_client__)
98 #define ALIGN_INT(val,alignment) (((val) + (alignment - 1)) & ~(alignment - 1))
100 #if defined(__native_client_codegen__) && defined(__native_client__)
101 /* End of text segment, set by linker.
102 * Dynamic text starts on the next allocated page.
105 char *next_dynamic_code_addr = NULL;
108 * This routine gets the next available bundle aligned
109 * pointer in the dynamic code section. It does not check
110 * for the section end, this error will be caught in the
114 allocate_code(intptr_t increment)
117 if (increment < 0) return NULL;
118 increment = increment & kNaClBundleMask ? (increment & ~kNaClBundleMask) + kNaClBundleSize : increment;
119 addr = next_dynamic_code_addr;
120 next_dynamic_code_addr += increment;
125 nacl_is_code_address (void *target)
127 return (char *)target < next_dynamic_code_addr;
130 const int kMaxPatchDepth = 32;
131 __thread unsigned char **patch_source_base = NULL;
132 __thread unsigned char **patch_dest_base = NULL;
133 __thread int *patch_alloc_size = NULL;
134 __thread int patch_current_depth = -1;
135 __thread int allow_target_modification = 1;
138 nacl_allow_target_modification (int val)
140 allow_target_modification = val;
144 nacl_jit_check_init ()
146 if (patch_source_base == NULL) {
147 patch_source_base = g_malloc (kMaxPatchDepth * sizeof(unsigned char *));
148 patch_dest_base = g_malloc (kMaxPatchDepth * sizeof(unsigned char *));
149 patch_alloc_size = g_malloc (kMaxPatchDepth * sizeof(int));
154 /* Given a patch target, modify the target such that patching will work when
155 * the code is copied to the data section.
158 nacl_modify_patch_target (unsigned char *target)
160 /* This seems like a bit of an ugly way to do this but the advantage
161 * is we don't have to worry about all the conditions in
162 * mono_resolve_patch_target, and it can be used by all the bare uses
168 if (!allow_target_modification) return target;
170 nacl_jit_check_init ();
171 sb = patch_source_base[patch_current_depth];
172 db = patch_dest_base[patch_current_depth];
174 if (target >= sb && (target < sb + patch_alloc_size[patch_current_depth])) {
175 /* Do nothing. target is in the section being generated.
176 * no need to modify, the disp will be the same either way.
179 int target_offset = target - db;
180 target = sb + target_offset;
186 nacl_inverse_modify_patch_target (unsigned char *target)
192 if (!allow_target_modification) return target;
194 nacl_jit_check_init ();
195 sb = patch_source_base[patch_current_depth];
196 db = patch_dest_base[patch_current_depth];
198 target_offset = target - sb;
199 target = db + target_offset;
204 #endif /* __native_client_codegen && __native_client__ */
206 #define VALLOC_FREELIST_SIZE 16
208 static CRITICAL_SECTION valloc_mutex;
209 static GHashTable *valloc_freelists;
212 codechunk_valloc (guint32 size)
217 if (!valloc_freelists) {
218 InitializeCriticalSection (&valloc_mutex);
219 valloc_freelists = g_hash_table_new (NULL, NULL);
223 * Keep a small freelist of memory blocks to decrease pressure on the kernel memory subsystem to avoid #3321.
225 EnterCriticalSection (&valloc_mutex);
226 freelist = g_hash_table_lookup (valloc_freelists, GUINT_TO_POINTER (size));
228 ptr = freelist->data;
229 memset (ptr, 0, size);
230 freelist = g_slist_remove_link (freelist, freelist);
231 g_hash_table_insert (valloc_freelists, GUINT_TO_POINTER (size), freelist);
233 ptr = mono_valloc (NULL, size + MIN_ALIGN - 1, MONO_PROT_RWX | ARCH_MAP_FLAGS);
235 LeaveCriticalSection (&valloc_mutex);
240 codechunk_vfree (void *ptr, guint32 size)
244 EnterCriticalSection (&valloc_mutex);
245 freelist = g_hash_table_lookup (valloc_freelists, GUINT_TO_POINTER (size));
246 if (!freelist || g_slist_length (freelist) < VALLOC_FREELIST_SIZE) {
247 freelist = g_slist_prepend (freelist, ptr);
248 g_hash_table_insert (valloc_freelists, GUINT_TO_POINTER (size), freelist);
250 mono_vfree (ptr, size);
252 LeaveCriticalSection (&valloc_mutex);
256 codechunk_cleanup (void)
261 if (!valloc_freelists)
263 g_hash_table_iter_init (&iter, valloc_freelists);
264 while (g_hash_table_iter_next (&iter, &key, &value)) {
265 GSList *freelist = value;
268 for (l = freelist; l; l = l->next) {
269 mono_vfree (l->data, GPOINTER_TO_UINT (key));
271 g_slist_free (freelist);
273 g_hash_table_destroy (valloc_freelists);
277 mono_code_manager_init (void)
282 mono_code_manager_cleanup (void)
284 codechunk_cleanup ();
288 * mono_code_manager_new:
290 * Creates a new code manager. A code manager can be used to allocate memory
291 * suitable for storing native code that can be later executed.
292 * A code manager allocates memory from the operating system in large chunks
293 * (typically 64KB in size) so that many methods can be allocated inside them
294 * close together, improving cache locality.
296 * Returns: the new code manager
299 mono_code_manager_new (void)
301 MonoCodeManager *cman = malloc (sizeof (MonoCodeManager));
304 cman->current = NULL;
308 #if defined(__native_client_codegen__) && defined(__native_client__)
309 if (next_dynamic_code_addr == NULL) {
310 const guint kPageMask = 0xFFFF; /* 64K pages */
311 next_dynamic_code_addr = (uintptr_t)(etext + kPageMask) & ~kPageMask;
312 #if defined (__GLIBC__)
313 /* TODO: For now, just jump 64MB ahead to avoid dynamic libraries. */
314 next_dynamic_code_addr += (uintptr_t)0x4000000;
316 /* Workaround bug in service runtime, unable to allocate */
317 /* from the first page in the dynamic code section. */
318 next_dynamic_code_addr += (uintptr_t)0x10000;
321 cman->hash = g_hash_table_new (NULL, NULL);
322 if (patch_source_base == NULL) {
323 patch_source_base = g_malloc (kMaxPatchDepth * sizeof(unsigned char *));
324 patch_dest_base = g_malloc (kMaxPatchDepth * sizeof(unsigned char *));
325 patch_alloc_size = g_malloc (kMaxPatchDepth * sizeof(int));
332 * mono_code_manager_new_dynamic:
334 * Creates a new code manager suitable for holding native code that can be
335 * used for single or small methods that need to be deallocated independently
336 * of other native code.
338 * Returns: the new code manager
341 mono_code_manager_new_dynamic (void)
343 MonoCodeManager *cman = mono_code_manager_new ();
350 free_chunklist (CodeChunk *chunk)
354 #if defined(HAVE_VALGRIND_MEMCHECK_H) && defined (VALGRIND_JIT_UNREGISTER_MAP)
355 int valgrind_unregister = 0;
356 if (RUNNING_ON_VALGRIND)
357 valgrind_unregister = 1;
358 #define valgrind_unregister(x) do { if (valgrind_unregister) { VALGRIND_JIT_UNREGISTER_MAP(NULL,x); } } while (0)
360 #define valgrind_unregister(x)
365 mono_profiler_code_chunk_destroy ((gpointer) dead->data);
367 if (dead->flags == CODE_FLAG_MMAP) {
368 codechunk_vfree (dead->data, dead->size);
369 /* valgrind_unregister(dead->data); */
370 } else if (dead->flags == CODE_FLAG_MALLOC) {
373 code_memory_used -= dead->size;
379 * mono_code_manager_destroy:
380 * @cman: a code manager
382 * Free all the memory associated with the code manager @cman.
385 mono_code_manager_destroy (MonoCodeManager *cman)
387 free_chunklist (cman->full);
388 free_chunklist (cman->current);
393 * mono_code_manager_invalidate:
394 * @cman: a code manager
396 * Fill all the memory with an invalid native code value
397 * so that any attempt to execute code allocated in the code
398 * manager @cman will fail. This is used for debugging purposes.
401 mono_code_manager_invalidate (MonoCodeManager *cman)
405 #if defined(__i386__) || defined(__x86_64__)
406 int fill_value = 0xcc; /* x86 break */
408 int fill_value = 0x2a;
411 for (chunk = cman->current; chunk; chunk = chunk->next)
412 memset (chunk->data, fill_value, chunk->size);
413 for (chunk = cman->full; chunk; chunk = chunk->next)
414 memset (chunk->data, fill_value, chunk->size);
418 * mono_code_manager_set_read_only:
419 * @cman: a code manager
421 * Make the code manager read only, so further allocation requests cause an assert.
424 mono_code_manager_set_read_only (MonoCodeManager *cman)
426 cman->read_only = TRUE;
430 * mono_code_manager_foreach:
431 * @cman: a code manager
432 * @func: a callback function pointer
433 * @user_data: additional data to pass to @func
435 * Invokes the callback @func for each different chunk of memory allocated
436 * in the code manager @cman.
439 mono_code_manager_foreach (MonoCodeManager *cman, MonoCodeManagerFunc func, void *user_data)
442 for (chunk = cman->current; chunk; chunk = chunk->next) {
443 if (func (chunk->data, chunk->size, chunk->bsize, user_data))
446 for (chunk = cman->full; chunk; chunk = chunk->next) {
447 if (func (chunk->data, chunk->size, chunk->bsize, user_data))
452 /* BIND_ROOM is the divisor for the chunck of code size dedicated
453 * to binding branches (branches not reachable with the immediate displacement)
454 * bind_size = size/BIND_ROOM;
455 * we should reduce it and make MIN_PAGES bigger for such systems
457 #if defined(__ppc__) || defined(__powerpc__)
465 new_codechunk (int dynamic, int size)
467 int minsize, flags = CODE_FLAG_MMAP;
468 int chunk_size, bsize = 0;
474 flags = CODE_FLAG_MALLOC;
477 pagesize = mono_pagesize ();
481 flags = CODE_FLAG_MALLOC;
483 minsize = pagesize * MIN_PAGES;
485 chunk_size = minsize;
488 chunk_size += pagesize - 1;
489 chunk_size &= ~ (pagesize - 1);
493 bsize = chunk_size / BIND_ROOM;
494 if (bsize < MIN_BSIZE)
496 bsize += MIN_ALIGN -1;
497 bsize &= ~ (MIN_ALIGN - 1);
498 if (chunk_size - size < bsize) {
499 chunk_size = size + bsize;
500 chunk_size += pagesize - 1;
501 chunk_size &= ~ (pagesize - 1);
505 if (flags == CODE_FLAG_MALLOC) {
506 ptr = dlmemalign (MIN_ALIGN, chunk_size + MIN_ALIGN - 1);
510 /* Allocate MIN_ALIGN-1 more than we need so we can still */
511 /* guarantee MIN_ALIGN alignment for individual allocs */
512 /* from mono_code_manager_reserve_align. */
513 ptr = codechunk_valloc (chunk_size);
518 if (flags == CODE_FLAG_MALLOC) {
520 /* Make sure the thunks area is zeroed */
521 memset (ptr, 0, bsize);
525 chunk = malloc (sizeof (CodeChunk));
527 if (flags == CODE_FLAG_MALLOC)
530 mono_vfree (ptr, chunk_size);
534 chunk->size = chunk_size;
536 chunk->flags = flags;
538 chunk->bsize = bsize;
539 mono_profiler_code_chunk_new((gpointer) chunk->data, chunk->size);
541 code_memory_used += chunk_size;
542 mono_runtime_resource_check_limit (MONO_RESOURCE_JIT_CODE, code_memory_used);
543 /*printf ("code chunk at: %p\n", ptr);*/
548 * mono_code_manager_reserve:
549 * @cman: a code manager
550 * @size: size of memory to allocate
551 * @alignment: power of two alignment value
553 * Allocates at least @size bytes of memory inside the code manager @cman.
555 * Returns: the pointer to the allocated memory or #NULL on failure
558 mono_code_manager_reserve_align (MonoCodeManager *cman, int size, int alignment)
560 #if !defined(__native_client__) || !defined(__native_client_codegen__)
561 CodeChunk *chunk, *prev;
563 guint32 align_mask = alignment - 1;
565 g_assert (!cman->read_only);
567 /* eventually allow bigger alignments, but we need to fix the dynamic alloc code to
570 g_assert (alignment <= MIN_ALIGN);
573 ++mono_stats.dynamic_code_alloc_count;
574 mono_stats.dynamic_code_bytes_count += size;
577 if (!cman->current) {
578 cman->current = new_codechunk (cman->dynamic, size);
583 for (chunk = cman->current; chunk; chunk = chunk->next) {
584 if (ALIGN_INT (chunk->pos, alignment) + size <= chunk->size) {
585 chunk->pos = ALIGN_INT (chunk->pos, alignment);
586 /* Align the chunk->data we add to chunk->pos */
587 /* or we can't guarantee proper alignment */
588 ptr = (void*)((((uintptr_t)chunk->data + align_mask) & ~(uintptr_t)align_mask) + chunk->pos);
589 chunk->pos = ((char*)ptr - chunk->data) + size;
594 * no room found, move one filled chunk to cman->full
595 * to keep cman->current from growing too much
598 for (chunk = cman->current; chunk; prev = chunk, chunk = chunk->next) {
599 if (chunk->pos + MIN_ALIGN * 4 <= chunk->size)
602 prev->next = chunk->next;
604 cman->current = chunk->next;
606 chunk->next = cman->full;
610 chunk = new_codechunk (cman->dynamic, size);
613 chunk->next = cman->current;
614 cman->current = chunk;
615 chunk->pos = ALIGN_INT (chunk->pos, alignment);
616 /* Align the chunk->data we add to chunk->pos */
617 /* or we can't guarantee proper alignment */
618 ptr = (void*)((((uintptr_t)chunk->data + align_mask) & ~(uintptr_t)align_mask) + chunk->pos);
619 chunk->pos = ((char*)ptr - chunk->data) + size;
622 unsigned char *temp_ptr, *code_ptr;
623 /* Round up size to next bundle */
624 alignment = kNaClBundleSize;
625 size = (size + kNaClBundleSize) & (~kNaClBundleMask);
626 /* Allocate a temp buffer */
627 temp_ptr = memalign (alignment, size);
628 g_assert (((uintptr_t)temp_ptr & kNaClBundleMask) == 0);
629 /* Allocate code space from the service runtime */
630 code_ptr = allocate_code (size);
631 /* Insert pointer to code space in hash, keyed by buffer ptr */
632 g_hash_table_insert (cman->hash, temp_ptr, code_ptr);
634 nacl_jit_check_init ();
636 patch_current_depth++;
637 patch_source_base[patch_current_depth] = temp_ptr;
638 patch_dest_base[patch_current_depth] = code_ptr;
639 patch_alloc_size[patch_current_depth] = size;
640 g_assert (patch_current_depth < kMaxPatchDepth);
646 * mono_code_manager_reserve:
647 * @cman: a code manager
648 * @size: size of memory to allocate
650 * Allocates at least @size bytes of memory inside the code manager @cman.
652 * Returns: the pointer to the allocated memory or #NULL on failure
655 mono_code_manager_reserve (MonoCodeManager *cman, int size)
657 return mono_code_manager_reserve_align (cman, size, MIN_ALIGN);
661 * mono_code_manager_commit:
662 * @cman: a code manager
663 * @data: the pointer returned by mono_code_manager_reserve ()
664 * @size: the size requested in the call to mono_code_manager_reserve ()
665 * @newsize: the new size to reserve
667 * If we reserved too much room for a method and we didn't allocate
668 * already from the code manager, we can get back the excess allocation
669 * for later use in the code manager.
672 mono_code_manager_commit (MonoCodeManager *cman, void *data, int size, int newsize)
674 #if !defined(__native_client__) || !defined(__native_client_codegen__)
675 g_assert (newsize <= size);
677 if (cman->current && (size != newsize) && (data == cman->current->data + cman->current->pos - size)) {
678 cman->current->pos -= size - newsize;
683 g_assert (newsize <= size);
684 code = g_hash_table_lookup (cman->hash, data);
685 g_assert (code != NULL);
686 /* Pad space after code with HLTs */
687 /* TODO: this is x86/amd64 specific */
688 while (newsize & kNaClBundleMask) {
689 *((char *)data + newsize) = 0xf4;
692 status = nacl_dyncode_create (code, data, newsize);
694 unsigned char *codep;
695 fprintf(stderr, "Error creating Native Client dynamic code section attempted to be\n"
696 "emitted at %p (hex dissasembly of code follows):\n", code);
697 for (codep = data; codep < data + newsize; codep++)
698 fprintf(stderr, "%02x ", *codep);
699 fprintf(stderr, "\n");
700 g_assert_not_reached ();
702 g_hash_table_remove (cman->hash, data);
703 g_assert (data == patch_source_base[patch_current_depth]);
704 g_assert (code == patch_dest_base[patch_current_depth]);
705 patch_current_depth--;
706 g_assert (patch_current_depth >= -1);
711 #if defined(__native_client_codegen__) && defined(__native_client__)
713 nacl_code_manager_get_code_dest (MonoCodeManager *cman, void *data)
715 return g_hash_table_lookup (cman->hash, data);
720 * mono_code_manager_size:
721 * @cman: a code manager
722 * @used_size: pointer to an integer for the result
724 * This function can be used to get statistics about a code manager:
725 * the integer pointed to by @used_size will contain how much
726 * memory is actually used inside the code managed @cman.
728 * Returns: the amount of memory allocated in @cman
731 mono_code_manager_size (MonoCodeManager *cman, int *used_size)
736 for (chunk = cman->current; chunk; chunk = chunk->next) {
740 for (chunk = cman->full; chunk; chunk = chunk->next) {