12 #define USE_DL_PREFIX 1
14 #include "mono-codeman.h"
15 #include "mono-mmap.h"
16 #include "mono-counters.h"
18 #include <mono/io-layer/io-layer.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>
27 #include <mono/mini/mini.h>
29 #include <mono/utils/mono-mutex.h>
32 static uintptr_t code_memory_used = 0;
33 static size_t dynamic_code_alloc_count;
34 static size_t dynamic_code_bytes_count;
35 static size_t dynamic_code_frees_count;
38 * AMD64 processors maintain icache coherency only for pages which are
39 * marked executable. Also, windows DEP requires us to obtain executable memory from
40 * malloc when using dynamic code managers. The system malloc can't do this so we use a
41 * slighly modified version of Doug Lea's Malloc package for this purpose:
42 * http://g.oswego.edu/dl/html/malloc.html
47 #if defined(__ia64__) || defined(__x86_64__) || defined (_WIN64)
49 * We require 16 byte alignment on amd64 so the fp literals embedded in the code are
50 * properly aligned for SSE2.
56 #ifdef __native_client_codegen__
57 /* For Google Native Client, all targets of indirect control flow need to */
58 /* be aligned to bundle boundary. 16 bytes on ARM, 32 bytes on x86.
59 * MIN_ALIGN was updated to force alignment for calls from
60 * tramp-<arch>.c to mono_global_codeman_reserve() */
61 /* and mono_domain_code_reserve(). */
63 #define MIN_ALIGN kNaClBundleSize
67 /* if a chunk has less than this amount of free space it's considered full */
68 #define MAX_WASTAGE 32
72 #define ARCH_MAP_FLAGS MONO_MMAP_32BIT
74 #define ARCH_MAP_FLAGS 0
77 #define MONO_PROT_RWX (MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_EXEC)
79 typedef struct _CodeChunck CodeChunk;
91 unsigned int flags: 8;
92 /* this number of bytes is available to resolve addresses far in memory */
93 unsigned int bsize: 24;
96 struct _MonoCodeManager {
103 #if defined(__native_client_codegen__) && defined(__native_client__)
108 #define ALIGN_INT(val,alignment) (((val) + (alignment - 1)) & ~(alignment - 1))
110 #if defined(__native_client_codegen__) && defined(__native_client__)
111 /* End of text segment, set by linker.
112 * Dynamic text starts on the next allocated page.
115 char *next_dynamic_code_addr = NULL;
118 * This routine gets the next available bundle aligned
119 * pointer in the dynamic code section. It does not check
120 * for the section end, this error will be caught in the
124 allocate_code(intptr_t increment)
127 if (increment < 0) return NULL;
128 increment = increment & kNaClBundleMask ? (increment & ~kNaClBundleMask) + kNaClBundleSize : increment;
129 addr = next_dynamic_code_addr;
130 next_dynamic_code_addr += increment;
135 nacl_is_code_address (void *target)
137 return (char *)target < next_dynamic_code_addr;
140 /* Fill code buffer with arch-specific NOPs. */
142 mono_nacl_fill_code_buffer (guint8 *data, int size);
144 #ifndef USE_JUMP_TABLES
145 const int kMaxPatchDepth = 32;
146 __thread unsigned char **patch_source_base = NULL;
147 __thread unsigned char **patch_dest_base = NULL;
148 __thread int *patch_alloc_size = NULL;
149 __thread int patch_current_depth = -1;
150 __thread int allow_target_modification = 1;
153 nacl_jit_check_init ()
155 if (patch_source_base == NULL) {
156 patch_source_base = g_malloc (kMaxPatchDepth * sizeof(unsigned char *));
157 patch_dest_base = g_malloc (kMaxPatchDepth * sizeof(unsigned char *));
158 patch_alloc_size = g_malloc (kMaxPatchDepth * sizeof(int));
164 nacl_allow_target_modification (int val)
166 #ifndef USE_JUMP_TABLES
167 allow_target_modification = val;
168 #endif /* USE_JUMP_TABLES */
171 /* Given a patch target, modify the target such that patching will work when
172 * the code is copied to the data section.
175 nacl_modify_patch_target (unsigned char *target)
178 * There's no need in patch tricks for jumptables,
179 * as we always patch same jumptable.
181 #ifndef USE_JUMP_TABLES
182 /* This seems like a bit of an ugly way to do this but the advantage
183 * is we don't have to worry about all the conditions in
184 * mono_resolve_patch_target, and it can be used by all the bare uses
190 if (!allow_target_modification) return target;
192 nacl_jit_check_init ();
193 sb = patch_source_base[patch_current_depth];
194 db = patch_dest_base[patch_current_depth];
196 if (target >= sb && (target < sb + patch_alloc_size[patch_current_depth])) {
197 /* Do nothing. target is in the section being generated.
198 * no need to modify, the disp will be the same either way.
201 int target_offset = target - db;
202 target = sb + target_offset;
209 nacl_inverse_modify_patch_target (unsigned char *target)
212 * There's no need in patch tricks for jumptables,
213 * as we always patch same jumptable.
215 #ifndef USE_JUMP_TABLES
220 if (!allow_target_modification) return target;
222 nacl_jit_check_init ();
223 sb = patch_source_base[patch_current_depth];
224 db = patch_dest_base[patch_current_depth];
226 target_offset = target - sb;
227 target = db + target_offset;
233 #endif /* __native_client_codegen && __native_client__ */
235 #define VALLOC_FREELIST_SIZE 16
237 static mono_mutex_t valloc_mutex;
238 static GHashTable *valloc_freelists;
241 codechunk_valloc (void *preferred, guint32 size)
246 if (!valloc_freelists) {
247 mono_mutex_init_recursive (&valloc_mutex);
248 valloc_freelists = g_hash_table_new (NULL, NULL);
252 * Keep a small freelist of memory blocks to decrease pressure on the kernel memory subsystem to avoid #3321.
254 mono_mutex_lock (&valloc_mutex);
255 freelist = g_hash_table_lookup (valloc_freelists, GUINT_TO_POINTER (size));
257 ptr = freelist->data;
258 memset (ptr, 0, size);
259 freelist = g_slist_delete_link (freelist, freelist);
260 g_hash_table_insert (valloc_freelists, GUINT_TO_POINTER (size), freelist);
262 ptr = mono_valloc (preferred, size, MONO_PROT_RWX | ARCH_MAP_FLAGS);
263 if (!ptr && preferred)
264 ptr = mono_valloc (NULL, size, MONO_PROT_RWX | ARCH_MAP_FLAGS);
266 mono_mutex_unlock (&valloc_mutex);
271 codechunk_vfree (void *ptr, guint32 size)
275 mono_mutex_lock (&valloc_mutex);
276 freelist = g_hash_table_lookup (valloc_freelists, GUINT_TO_POINTER (size));
277 if (!freelist || g_slist_length (freelist) < VALLOC_FREELIST_SIZE) {
278 freelist = g_slist_prepend (freelist, ptr);
279 g_hash_table_insert (valloc_freelists, GUINT_TO_POINTER (size), freelist);
281 mono_vfree (ptr, size);
283 mono_mutex_unlock (&valloc_mutex);
287 codechunk_cleanup (void)
292 if (!valloc_freelists)
294 g_hash_table_iter_init (&iter, valloc_freelists);
295 while (g_hash_table_iter_next (&iter, &key, &value)) {
296 GSList *freelist = value;
299 for (l = freelist; l; l = l->next) {
300 mono_vfree (l->data, GPOINTER_TO_UINT (key));
302 g_slist_free (freelist);
304 g_hash_table_destroy (valloc_freelists);
308 mono_code_manager_init (void)
310 mono_counters_register ("Dynamic code allocs", MONO_COUNTER_JIT | MONO_COUNTER_ULONG, &dynamic_code_alloc_count);
311 mono_counters_register ("Dynamic code bytes", MONO_COUNTER_JIT | MONO_COUNTER_ULONG, &dynamic_code_bytes_count);
312 mono_counters_register ("Dynamic code frees", MONO_COUNTER_JIT | MONO_COUNTER_ULONG, &dynamic_code_frees_count);
316 mono_code_manager_cleanup (void)
318 codechunk_cleanup ();
322 * mono_code_manager_new:
324 * Creates a new code manager. A code manager can be used to allocate memory
325 * suitable for storing native code that can be later executed.
326 * A code manager allocates memory from the operating system in large chunks
327 * (typically 64KB in size) so that many methods can be allocated inside them
328 * close together, improving cache locality.
330 * Returns: the new code manager
333 mono_code_manager_new (void)
335 MonoCodeManager *cman = g_malloc0 (sizeof (MonoCodeManager));
338 #if defined(__native_client_codegen__) && defined(__native_client__)
339 if (next_dynamic_code_addr == NULL) {
340 const guint kPageMask = 0xFFFF; /* 64K pages */
341 next_dynamic_code_addr = (uintptr_t)(etext + kPageMask) & ~kPageMask;
342 #if defined (__GLIBC__)
343 /* TODO: For now, just jump 64MB ahead to avoid dynamic libraries. */
344 next_dynamic_code_addr += (uintptr_t)0x4000000;
346 /* Workaround bug in service runtime, unable to allocate */
347 /* from the first page in the dynamic code section. */
348 next_dynamic_code_addr += (uintptr_t)0x10000;
351 cman->hash = g_hash_table_new (NULL, NULL);
352 # ifndef USE_JUMP_TABLES
353 if (patch_source_base == NULL) {
354 patch_source_base = g_malloc (kMaxPatchDepth * sizeof(unsigned char *));
355 patch_dest_base = g_malloc (kMaxPatchDepth * sizeof(unsigned char *));
356 patch_alloc_size = g_malloc (kMaxPatchDepth * sizeof(int));
364 * mono_code_manager_new_dynamic:
366 * Creates a new code manager suitable for holding native code that can be
367 * used for single or small methods that need to be deallocated independently
368 * of other native code.
369 * BIND_SIZE is the amount of memory reserved for storing thunks. If its 0,
370 * the default size is used.
372 * Returns: the new code manager
375 mono_code_manager_new_dynamic (int bind_size)
377 MonoCodeManager *cman = mono_code_manager_new ();
379 cman->bind_size = bind_size;
385 free_chunklist (CodeChunk *chunk)
389 #if defined(HAVE_VALGRIND_MEMCHECK_H) && defined (VALGRIND_JIT_UNREGISTER_MAP)
390 int valgrind_unregister = 0;
391 if (RUNNING_ON_VALGRIND)
392 valgrind_unregister = 1;
393 #define valgrind_unregister(x) do { if (valgrind_unregister) { VALGRIND_JIT_UNREGISTER_MAP(NULL,x); } } while (0)
395 #define valgrind_unregister(x)
400 mono_profiler_code_chunk_destroy ((gpointer) dead->data);
402 if (dead->flags == CODE_FLAG_MMAP) {
403 codechunk_vfree (dead->data, dead->size);
404 /* valgrind_unregister(dead->data); */
405 } else if (dead->flags == CODE_FLAG_MALLOC) {
408 code_memory_used -= dead->size;
414 * mono_code_manager_destroy:
415 * @cman: a code manager
417 * Free all the memory associated with the code manager @cman.
420 mono_code_manager_destroy (MonoCodeManager *cman)
422 free_chunklist (cman->full);
423 free_chunklist (cman->current);
428 * mono_code_manager_invalidate:
429 * @cman: a code manager
431 * Fill all the memory with an invalid native code value
432 * so that any attempt to execute code allocated in the code
433 * manager @cman will fail. This is used for debugging purposes.
436 mono_code_manager_invalidate (MonoCodeManager *cman)
440 #if defined(__i386__) || defined(__x86_64__)
441 int fill_value = 0xcc; /* x86 break */
443 int fill_value = 0x2a;
446 for (chunk = cman->current; chunk; chunk = chunk->next)
447 memset (chunk->data, fill_value, chunk->size);
448 for (chunk = cman->full; chunk; chunk = chunk->next)
449 memset (chunk->data, fill_value, chunk->size);
453 * mono_code_manager_set_read_only:
454 * @cman: a code manager
456 * Make the code manager read only, so further allocation requests cause an assert.
459 mono_code_manager_set_read_only (MonoCodeManager *cman)
461 cman->read_only = TRUE;
465 * mono_code_manager_foreach:
466 * @cman: a code manager
467 * @func: a callback function pointer
468 * @user_data: additional data to pass to @func
470 * Invokes the callback @func for each different chunk of memory allocated
471 * in the code manager @cman.
474 mono_code_manager_foreach (MonoCodeManager *cman, MonoCodeManagerFunc func, void *user_data)
477 for (chunk = cman->current; chunk; chunk = chunk->next) {
478 if (func (chunk->data, chunk->size, chunk->bsize, user_data))
481 for (chunk = cman->full; chunk; chunk = chunk->next) {
482 if (func (chunk->data, chunk->size, chunk->bsize, user_data))
487 /* BIND_ROOM is the divisor for the chunck of code size dedicated
488 * to binding branches (branches not reachable with the immediate displacement)
489 * bind_size = size/BIND_ROOM;
490 * we should reduce it and make MIN_PAGES bigger for such systems
492 #if defined(__ppc__) || defined(__powerpc__)
498 #if defined(TARGET_ARM64)
503 new_codechunk (CodeChunk *last, int dynamic, int size, int bind_size)
505 int minsize, flags = CODE_FLAG_MMAP;
506 int chunk_size, bsize = 0;
512 flags = CODE_FLAG_MALLOC;
515 pagesize = mono_pagesize ();
519 flags = CODE_FLAG_MALLOC;
521 minsize = pagesize * MIN_PAGES;
523 chunk_size = minsize;
525 /* Allocate MIN_ALIGN-1 more than we need so we can still */
526 /* guarantee MIN_ALIGN alignment for individual allocs */
527 /* from mono_code_manager_reserve_align. */
528 size += MIN_ALIGN - 1;
529 size &= ~(MIN_ALIGN - 1);
531 chunk_size += pagesize - 1;
532 chunk_size &= ~ (pagesize - 1);
540 /* Reserve more space since there are no other chunks we might use if this one gets full */
541 bsize = (chunk_size * 2) / BIND_ROOM;
543 bsize = chunk_size / BIND_ROOM;
545 if (bsize < MIN_BSIZE)
547 bsize += MIN_ALIGN -1;
548 bsize &= ~ (MIN_ALIGN - 1);
549 if (chunk_size - size < bsize) {
550 chunk_size = size + bsize;
552 chunk_size += pagesize - 1;
553 chunk_size &= ~ (pagesize - 1);
558 if (flags == CODE_FLAG_MALLOC) {
559 ptr = dlmemalign (MIN_ALIGN, chunk_size + MIN_ALIGN - 1);
563 /* Try to allocate code chunks next to each other to help the VM */
566 ptr = codechunk_valloc ((guint8*)last->data + last->size, chunk_size);
568 ptr = codechunk_valloc (NULL, chunk_size);
573 if (flags == CODE_FLAG_MALLOC) {
575 /* Make sure the thunks area is zeroed */
576 memset (ptr, 0, bsize);
580 chunk = malloc (sizeof (CodeChunk));
582 if (flags == CODE_FLAG_MALLOC)
585 mono_vfree (ptr, chunk_size);
589 chunk->size = chunk_size;
591 chunk->flags = flags;
593 chunk->bsize = bsize;
594 mono_profiler_code_chunk_new((gpointer) chunk->data, chunk->size);
596 code_memory_used += chunk_size;
597 mono_runtime_resource_check_limit (MONO_RESOURCE_JIT_CODE, code_memory_used);
598 /*printf ("code chunk at: %p\n", ptr);*/
603 * mono_code_manager_reserve:
604 * @cman: a code manager
605 * @size: size of memory to allocate
606 * @alignment: power of two alignment value
608 * Allocates at least @size bytes of memory inside the code manager @cman.
610 * Returns: the pointer to the allocated memory or #NULL on failure
613 mono_code_manager_reserve_align (MonoCodeManager *cman, int size, int alignment)
615 #if !defined(__native_client__) || !defined(__native_client_codegen__)
616 CodeChunk *chunk, *prev;
618 guint32 align_mask = alignment - 1;
620 g_assert (!cman->read_only);
622 /* eventually allow bigger alignments, but we need to fix the dynamic alloc code to
625 g_assert (alignment <= MIN_ALIGN);
628 ++dynamic_code_alloc_count;
629 dynamic_code_bytes_count += size;
632 if (!cman->current) {
633 cman->current = new_codechunk (cman->last, cman->dynamic, size, cman->bind_size);
636 cman->last = cman->current;
639 for (chunk = cman->current; chunk; chunk = chunk->next) {
640 if (ALIGN_INT (chunk->pos, alignment) + size <= chunk->size) {
641 chunk->pos = ALIGN_INT (chunk->pos, alignment);
642 /* Align the chunk->data we add to chunk->pos */
643 /* or we can't guarantee proper alignment */
644 ptr = (void*)((((uintptr_t)chunk->data + align_mask) & ~(uintptr_t)align_mask) + chunk->pos);
645 chunk->pos = ((char*)ptr - chunk->data) + size;
650 * no room found, move one filled chunk to cman->full
651 * to keep cman->current from growing too much
654 for (chunk = cman->current; chunk; prev = chunk, chunk = chunk->next) {
655 if (chunk->pos + MIN_ALIGN * 4 <= chunk->size)
658 prev->next = chunk->next;
660 cman->current = chunk->next;
662 chunk->next = cman->full;
666 chunk = new_codechunk (cman->last, cman->dynamic, size, cman->bind_size);
669 chunk->next = cman->current;
670 cman->current = chunk;
671 cman->last = cman->current;
672 chunk->pos = ALIGN_INT (chunk->pos, alignment);
673 /* Align the chunk->data we add to chunk->pos */
674 /* or we can't guarantee proper alignment */
675 ptr = (void*)((((uintptr_t)chunk->data + align_mask) & ~(uintptr_t)align_mask) + chunk->pos);
676 chunk->pos = ((char*)ptr - chunk->data) + size;
679 unsigned char *temp_ptr, *code_ptr;
680 /* Round up size to next bundle */
681 alignment = kNaClBundleSize;
682 size = (size + kNaClBundleSize) & (~kNaClBundleMask);
683 /* Allocate a temp buffer */
684 temp_ptr = memalign (alignment, size);
685 g_assert (((uintptr_t)temp_ptr & kNaClBundleMask) == 0);
686 /* Allocate code space from the service runtime */
687 code_ptr = allocate_code (size);
688 /* Insert pointer to code space in hash, keyed by buffer ptr */
689 g_hash_table_insert (cman->hash, temp_ptr, code_ptr);
691 #ifndef USE_JUMP_TABLES
692 nacl_jit_check_init ();
694 patch_current_depth++;
695 patch_source_base[patch_current_depth] = temp_ptr;
696 patch_dest_base[patch_current_depth] = code_ptr;
697 patch_alloc_size[patch_current_depth] = size;
698 g_assert (patch_current_depth < kMaxPatchDepth);
706 * mono_code_manager_reserve:
707 * @cman: a code manager
708 * @size: size of memory to allocate
710 * Allocates at least @size bytes of memory inside the code manager @cman.
712 * Returns: the pointer to the allocated memory or #NULL on failure
715 mono_code_manager_reserve (MonoCodeManager *cman, int size)
717 return mono_code_manager_reserve_align (cman, size, MIN_ALIGN);
721 * mono_code_manager_commit:
722 * @cman: a code manager
723 * @data: the pointer returned by mono_code_manager_reserve ()
724 * @size: the size requested in the call to mono_code_manager_reserve ()
725 * @newsize: the new size to reserve
727 * If we reserved too much room for a method and we didn't allocate
728 * already from the code manager, we can get back the excess allocation
729 * for later use in the code manager.
732 mono_code_manager_commit (MonoCodeManager *cman, void *data, int size, int newsize)
734 #if !defined(__native_client__) || !defined(__native_client_codegen__)
735 g_assert (newsize <= size);
737 if (cman->current && (size != newsize) && (data == cman->current->data + cman->current->pos - size)) {
738 cman->current->pos -= size - newsize;
743 g_assert (NACL_BUNDLE_ALIGN_UP(newsize) <= size);
744 code = g_hash_table_lookup (cman->hash, data);
745 g_assert (code != NULL);
746 mono_nacl_fill_code_buffer ((uint8_t*)data + newsize, size - newsize);
747 newsize = NACL_BUNDLE_ALIGN_UP(newsize);
748 g_assert ((GPOINTER_TO_UINT (data) & kNaClBundleMask) == 0);
749 g_assert ((newsize & kNaClBundleMask) == 0);
750 status = nacl_dyncode_create (code, data, newsize);
752 unsigned char *codep;
753 fprintf(stderr, "Error creating Native Client dynamic code section attempted to be\n"
754 "emitted at %p (hex dissasembly of code follows):\n", code);
755 for (codep = data; codep < data + newsize; codep++)
756 fprintf(stderr, "%02x ", *codep);
757 fprintf(stderr, "\n");
758 g_assert_not_reached ();
760 g_hash_table_remove (cman->hash, data);
761 # ifndef USE_JUMP_TABLES
762 g_assert (data == patch_source_base[patch_current_depth]);
763 g_assert (code == patch_dest_base[patch_current_depth]);
764 patch_current_depth--;
765 g_assert (patch_current_depth >= -1);
771 #if defined(__native_client_codegen__) && defined(__native_client__)
773 nacl_code_manager_get_code_dest (MonoCodeManager *cman, void *data)
775 return g_hash_table_lookup (cman->hash, data);
780 * mono_code_manager_size:
781 * @cman: a code manager
782 * @used_size: pointer to an integer for the result
784 * This function can be used to get statistics about a code manager:
785 * the integer pointed to by @used_size will contain how much
786 * memory is actually used inside the code managed @cman.
788 * Returns: the amount of memory allocated in @cman
791 mono_code_manager_size (MonoCodeManager *cman, int *used_size)
796 for (chunk = cman->current; chunk; chunk = chunk->next) {
800 for (chunk = cman->full; chunk; chunk = chunk->next) {
809 #ifdef __native_client_codegen__
810 # if defined(TARGET_ARM)
811 /* Fill empty space with UDF instruction used as halt on ARM. */
813 mono_nacl_fill_code_buffer (guint8 *data, int size)
815 guint32* data32 = (guint32*)data;
817 g_assert(size % 4 == 0);
818 for (i = 0; i < size / 4; i++)
819 data32[i] = 0xE7FEDEFF;
821 # elif (defined(TARGET_X86) || defined(TARGET_AMD64))
822 /* Fill empty space with HLT instruction */
824 mono_nacl_fill_code_buffer(guint8 *data, int size)
826 memset (data, 0xf4, size);