2 * profiler.c: Profiler interface for Mono
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
12 #include "mono/metadata/profiler-private.h"
13 #include "mono/metadata/profiler-default.h"
14 #include "mono/metadata/debug-helpers.h"
15 #include "mono/metadata/mono-debug.h"
16 #include "mono/metadata/debug-mono-symfile.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include "mono/metadata/class-internals.h"
19 #include "mono/metadata/domain-internals.h"
20 #include "mono/metadata/gc-internal.h"
21 #include "mono/io-layer/io-layer.h"
22 #include "mono/utils/mono-dl.h"
27 #ifdef HAVE_SYS_TIME_H
30 #ifdef HAVE_BACKTRACE_SYMBOLS
34 typedef struct _ProfilerDesc ProfilerDesc;
35 struct _ProfilerDesc {
37 MonoProfiler *profiler;
38 MonoProfileFlags events;
40 MonoProfileAppDomainFunc domain_start_load;
41 MonoProfileAppDomainResult domain_end_load;
42 MonoProfileAppDomainFunc domain_start_unload;
43 MonoProfileAppDomainFunc domain_end_unload;
45 MonoProfileAssemblyFunc assembly_start_load;
46 MonoProfileAssemblyResult assembly_end_load;
47 MonoProfileAssemblyFunc assembly_start_unload;
48 MonoProfileAssemblyFunc assembly_end_unload;
50 MonoProfileModuleFunc module_start_load;
51 MonoProfileModuleResult module_end_load;
52 MonoProfileModuleFunc module_start_unload;
53 MonoProfileModuleFunc module_end_unload;
55 MonoProfileClassFunc class_start_load;
56 MonoProfileClassResult class_end_load;
57 MonoProfileClassFunc class_start_unload;
58 MonoProfileClassFunc class_end_unload;
60 MonoProfileMethodFunc jit_start;
61 MonoProfileMethodResult jit_end;
62 MonoProfileJitResult jit_end2;
63 MonoProfileMethodFunc method_free;
64 MonoProfileMethodFunc method_start_invoke;
65 MonoProfileMethodFunc method_end_invoke;
66 MonoProfileMethodResult man_unman_transition;
67 MonoProfileAllocFunc allocation_cb;
68 MonoProfileMonitorFunc monitor_event_cb;
69 MonoProfileStatFunc statistical_cb;
70 MonoProfileStatCallChainFunc statistical_call_chain_cb;
71 int statistical_call_chain_depth;
72 MonoProfilerCallChainStrategy statistical_call_chain_strategy;
73 MonoProfileMethodFunc method_enter;
74 MonoProfileMethodFunc method_leave;
76 MonoProfileExceptionFunc exception_throw_cb;
77 MonoProfileMethodFunc exception_method_leave_cb;
78 MonoProfileExceptionClauseFunc exception_clause_cb;
80 MonoProfileIomapFunc iomap_cb;
82 MonoProfileThreadFunc thread_start;
83 MonoProfileThreadFunc thread_end;
85 MonoProfileCoverageFilterFunc coverage_filter_cb;
87 MonoProfileFunc shutdown_callback;
89 MonoProfileGCFunc gc_event;
90 MonoProfileGCResizeFunc gc_heap_resize;
91 MonoProfileGCMoveFunc gc_moves;
92 MonoProfileGCHandleFunc gc_handle;
94 MonoProfileFunc runtime_initialized_event;
96 MonoProfilerCodeChunkNew code_chunk_new;
97 MonoProfilerCodeChunkDestroy code_chunk_destroy;
98 MonoProfilerCodeBufferNew code_buffer_new;
101 static ProfilerDesc *prof_list = NULL;
103 #define mono_profiler_coverage_lock() EnterCriticalSection (&profiler_coverage_mutex)
104 #define mono_profiler_coverage_unlock() LeaveCriticalSection (&profiler_coverage_mutex)
105 static CRITICAL_SECTION profiler_coverage_mutex;
107 /* this is directly accessible to other mono libs.
108 * It is the ORed value of all the profiler's events.
110 MonoProfileFlags mono_profiler_events;
113 * mono_profiler_install:
114 * @prof: a MonoProfiler structure pointer, or a pointer to a derived structure.
115 * @callback: the function to invoke at shutdown
117 * Use mono_profiler_install to activate profiling in the Mono runtime.
118 * Typically developers of new profilers will create a new structure whose
119 * first field is a MonoProfiler and put any extra information that they need
120 * to access from the various profiling callbacks there.
124 mono_profiler_install (MonoProfiler *prof, MonoProfileFunc callback)
126 ProfilerDesc *desc = g_new0 (ProfilerDesc, 1);
128 InitializeCriticalSection (&profiler_coverage_mutex);
129 desc->profiler = prof;
130 desc->shutdown_callback = callback;
131 desc->next = prof_list;
136 * mono_profiler_set_events:
137 * @events: an ORed set of values made up of MONO_PROFILER_ flags
139 * The events descriped in the @events argument is a set of flags
140 * that represent which profiling events must be triggered. For
141 * example if you have registered a set of methods for tracking
142 * JIT compilation start and end with mono_profiler_install_jit_compile,
143 * you will want to pass the MONO_PROFILE_JIT_COMPILATION flag to
146 * You can call mono_profile_set_events more than once and you can
147 * do this at runtime to modify which methods are invoked.
150 mono_profiler_set_events (MonoProfileFlags events)
153 MonoProfileFlags value = 0;
155 prof_list->events = events;
156 for (prof = prof_list; prof; prof = prof->next)
157 value |= prof->events;
158 mono_profiler_events = value;
162 * mono_profiler_get_events:
164 * Returns a list of active events that will be intercepted.
167 mono_profiler_get_events (void)
169 return mono_profiler_events;
173 * mono_profiler_install_enter_leave:
174 * @enter: the routine to be called on each method entry
175 * @fleave: the routine to be called each time a method returns
177 * Use this routine to install routines that will be called everytime
178 * a method enters and leaves. The routines will receive as an argument
179 * the MonoMethod representing the method that is entering or leaving.
182 mono_profiler_install_enter_leave (MonoProfileMethodFunc enter, MonoProfileMethodFunc fleave)
186 prof_list->method_enter = enter;
187 prof_list->method_leave = fleave;
191 * mono_profiler_install_jit_compile:
192 * @start: the routine to be called when the JIT process starts.
193 * @end: the routine to be called when the JIT process ends.
195 * Use this routine to install routines that will be called when JIT
196 * compilation of a method starts and completes.
199 mono_profiler_install_jit_compile (MonoProfileMethodFunc start, MonoProfileMethodResult end)
203 prof_list->jit_start = start;
204 prof_list->jit_end = end;
208 mono_profiler_install_jit_end (MonoProfileJitResult end)
212 prof_list->jit_end2 = end;
216 mono_profiler_install_method_free (MonoProfileMethodFunc callback)
220 prof_list->method_free = callback;
224 mono_profiler_install_method_invoke (MonoProfileMethodFunc start, MonoProfileMethodFunc end)
228 prof_list->method_start_invoke = start;
229 prof_list->method_end_invoke = end;
233 mono_profiler_install_thread (MonoProfileThreadFunc start, MonoProfileThreadFunc end)
237 prof_list->thread_start = start;
238 prof_list->thread_end = end;
242 mono_profiler_install_transition (MonoProfileMethodResult callback)
246 prof_list->man_unman_transition = callback;
250 mono_profiler_install_allocation (MonoProfileAllocFunc callback)
254 prof_list->allocation_cb = callback;
258 mono_profiler_install_monitor (MonoProfileMonitorFunc callback)
262 prof_list->monitor_event_cb = callback;
266 mono_profiler_install_statistical (MonoProfileStatFunc callback)
270 prof_list->statistical_cb = callback;
274 mono_profiler_install_statistical_call_chain (MonoProfileStatCallChainFunc callback, int call_chain_depth, MonoProfilerCallChainStrategy call_chain_strategy) {
277 if (call_chain_depth > MONO_PROFILER_MAX_STAT_CALL_CHAIN_DEPTH) {
278 call_chain_depth = MONO_PROFILER_MAX_STAT_CALL_CHAIN_DEPTH;
280 if ((call_chain_strategy >= MONO_PROFILER_CALL_CHAIN_INVALID) || (call_chain_strategy < MONO_PROFILER_CALL_CHAIN_NONE)) {
281 call_chain_strategy = MONO_PROFILER_CALL_CHAIN_NONE;
283 prof_list->statistical_call_chain_cb = callback;
284 prof_list->statistical_call_chain_depth = call_chain_depth;
285 prof_list->statistical_call_chain_strategy = call_chain_strategy;
289 mono_profiler_stat_get_call_chain_depth (void) {
290 if (prof_list && prof_list->statistical_call_chain_cb != NULL) {
291 return prof_list->statistical_call_chain_depth;
297 MonoProfilerCallChainStrategy
298 mono_profiler_stat_get_call_chain_strategy (void) {
299 if (prof_list && prof_list->statistical_call_chain_cb != NULL) {
300 return prof_list->statistical_call_chain_strategy;
302 return MONO_PROFILER_CALL_CHAIN_NONE;
306 void mono_profiler_install_exception (MonoProfileExceptionFunc throw_callback, MonoProfileMethodFunc exc_method_leave, MonoProfileExceptionClauseFunc clause_callback)
310 prof_list->exception_throw_cb = throw_callback;
311 prof_list->exception_method_leave_cb = exc_method_leave;
312 prof_list->exception_clause_cb = clause_callback;
316 mono_profiler_install_coverage_filter (MonoProfileCoverageFilterFunc callback)
320 prof_list->coverage_filter_cb = callback;
324 mono_profiler_install_appdomain (MonoProfileAppDomainFunc start_load, MonoProfileAppDomainResult end_load,
325 MonoProfileAppDomainFunc start_unload, MonoProfileAppDomainFunc end_unload)
330 prof_list->domain_start_load = start_load;
331 prof_list->domain_end_load = end_load;
332 prof_list->domain_start_unload = start_unload;
333 prof_list->domain_end_unload = end_unload;
337 mono_profiler_install_assembly (MonoProfileAssemblyFunc start_load, MonoProfileAssemblyResult end_load,
338 MonoProfileAssemblyFunc start_unload, MonoProfileAssemblyFunc end_unload)
342 prof_list->assembly_start_load = start_load;
343 prof_list->assembly_end_load = end_load;
344 prof_list->assembly_start_unload = start_unload;
345 prof_list->assembly_end_unload = end_unload;
349 mono_profiler_install_module (MonoProfileModuleFunc start_load, MonoProfileModuleResult end_load,
350 MonoProfileModuleFunc start_unload, MonoProfileModuleFunc end_unload)
354 prof_list->module_start_load = start_load;
355 prof_list->module_end_load = end_load;
356 prof_list->module_start_unload = start_unload;
357 prof_list->module_end_unload = end_unload;
361 mono_profiler_install_class (MonoProfileClassFunc start_load, MonoProfileClassResult end_load,
362 MonoProfileClassFunc start_unload, MonoProfileClassFunc end_unload)
366 prof_list->class_start_load = start_load;
367 prof_list->class_end_load = end_load;
368 prof_list->class_start_unload = start_unload;
369 prof_list->class_end_unload = end_unload;
373 mono_profiler_method_enter (MonoMethod *method)
376 for (prof = prof_list; prof; prof = prof->next) {
377 if ((prof->events & MONO_PROFILE_ENTER_LEAVE) && prof->method_enter)
378 prof->method_enter (prof->profiler, method);
383 mono_profiler_method_leave (MonoMethod *method)
386 for (prof = prof_list; prof; prof = prof->next) {
387 if ((prof->events & MONO_PROFILE_ENTER_LEAVE) && prof->method_leave)
388 prof->method_leave (prof->profiler, method);
393 mono_profiler_method_jit (MonoMethod *method)
396 for (prof = prof_list; prof; prof = prof->next) {
397 if ((prof->events & MONO_PROFILE_JIT_COMPILATION) && prof->jit_start)
398 prof->jit_start (prof->profiler, method);
403 mono_profiler_method_end_jit (MonoMethod *method, MonoJitInfo* jinfo, int result)
406 for (prof = prof_list; prof; prof = prof->next) {
407 if ((prof->events & MONO_PROFILE_JIT_COMPILATION)) {
409 prof->jit_end (prof->profiler, method, result);
411 prof->jit_end2 (prof->profiler, method, jinfo, result);
417 mono_profiler_method_free (MonoMethod *method)
420 for (prof = prof_list; prof; prof = prof->next) {
421 if ((prof->events & MONO_PROFILE_METHOD_EVENTS) && prof->method_free)
422 prof->method_free (prof->profiler, method);
427 mono_profiler_method_start_invoke (MonoMethod *method)
430 for (prof = prof_list; prof; prof = prof->next) {
431 if ((prof->events & MONO_PROFILE_METHOD_EVENTS) && prof->method_start_invoke)
432 prof->method_start_invoke (prof->profiler, method);
437 mono_profiler_method_end_invoke (MonoMethod *method)
440 for (prof = prof_list; prof; prof = prof->next) {
441 if ((prof->events & MONO_PROFILE_METHOD_EVENTS) && prof->method_end_invoke)
442 prof->method_end_invoke (prof->profiler, method);
447 mono_profiler_code_transition (MonoMethod *method, int result)
450 for (prof = prof_list; prof; prof = prof->next) {
451 if ((prof->events & MONO_PROFILE_TRANSITIONS) && prof->man_unman_transition)
452 prof->man_unman_transition (prof->profiler, method, result);
457 mono_profiler_allocation (MonoObject *obj, MonoClass *klass)
460 for (prof = prof_list; prof; prof = prof->next) {
461 if ((prof->events & MONO_PROFILE_ALLOCATIONS) && prof->allocation_cb)
462 prof->allocation_cb (prof->profiler, obj, klass);
467 mono_profiler_monitor_event (MonoObject *obj, MonoProfilerMonitorEvent event) {
469 for (prof = prof_list; prof; prof = prof->next) {
470 if ((prof->events & MONO_PROFILE_MONITOR_EVENTS) && prof->monitor_event_cb)
471 prof->monitor_event_cb (prof->profiler, obj, event);
476 mono_profiler_stat_hit (guchar *ip, void *context)
479 for (prof = prof_list; prof; prof = prof->next) {
480 if ((prof->events & MONO_PROFILE_STATISTICAL) && prof->statistical_cb)
481 prof->statistical_cb (prof->profiler, ip, context);
486 mono_profiler_stat_call_chain (int call_chain_depth, guchar **ips, void *context)
489 for (prof = prof_list; prof; prof = prof->next) {
490 if ((prof->events & MONO_PROFILE_STATISTICAL) && prof->statistical_call_chain_cb)
491 prof->statistical_call_chain_cb (prof->profiler, call_chain_depth, ips, context);
496 mono_profiler_exception_thrown (MonoObject *exception)
499 for (prof = prof_list; prof; prof = prof->next) {
500 if ((prof->events & MONO_PROFILE_EXCEPTIONS) && prof->exception_throw_cb)
501 prof->exception_throw_cb (prof->profiler, exception);
506 mono_profiler_exception_method_leave (MonoMethod *method)
509 for (prof = prof_list; prof; prof = prof->next) {
510 if ((prof->events & MONO_PROFILE_EXCEPTIONS) && prof->exception_method_leave_cb)
511 prof->exception_method_leave_cb (prof->profiler, method);
516 mono_profiler_exception_clause_handler (MonoMethod *method, int clause_type, int clause_num)
519 for (prof = prof_list; prof; prof = prof->next) {
520 if ((prof->events & MONO_PROFILE_EXCEPTIONS) && prof->exception_clause_cb)
521 prof->exception_clause_cb (prof->profiler, method, clause_type, clause_num);
526 mono_profiler_thread_start (gsize tid)
529 for (prof = prof_list; prof; prof = prof->next) {
530 if ((prof->events & MONO_PROFILE_THREADS) && prof->thread_start)
531 prof->thread_start (prof->profiler, tid);
536 mono_profiler_thread_end (gsize tid)
539 for (prof = prof_list; prof; prof = prof->next) {
540 if ((prof->events & MONO_PROFILE_THREADS) && prof->thread_end)
541 prof->thread_end (prof->profiler, tid);
546 mono_profiler_assembly_event (MonoAssembly *assembly, int code)
549 for (prof = prof_list; prof; prof = prof->next) {
550 if (!(prof->events & MONO_PROFILE_ASSEMBLY_EVENTS))
554 case MONO_PROFILE_START_LOAD:
555 if (prof->assembly_start_load)
556 prof->assembly_start_load (prof->profiler, assembly);
558 case MONO_PROFILE_START_UNLOAD:
559 if (prof->assembly_start_unload)
560 prof->assembly_start_unload (prof->profiler, assembly);
562 case MONO_PROFILE_END_UNLOAD:
563 if (prof->assembly_end_unload)
564 prof->assembly_end_unload (prof->profiler, assembly);
567 g_assert_not_reached ();
573 mono_profiler_assembly_loaded (MonoAssembly *assembly, int result)
576 for (prof = prof_list; prof; prof = prof->next) {
577 if ((prof->events & MONO_PROFILE_ASSEMBLY_EVENTS) && prof->assembly_end_load)
578 prof->assembly_end_load (prof->profiler, assembly, result);
582 void mono_profiler_iomap (char *report, const char *pathname, const char *new_pathname)
585 for (prof = prof_list; prof; prof = prof->next) {
586 if ((prof->events & MONO_PROFILE_IOMAP_EVENTS) && prof->iomap_cb)
587 prof->iomap_cb (prof->profiler, report, pathname, new_pathname);
592 mono_profiler_module_event (MonoImage *module, int code)
595 for (prof = prof_list; prof; prof = prof->next) {
596 if (!(prof->events & MONO_PROFILE_MODULE_EVENTS))
600 case MONO_PROFILE_START_LOAD:
601 if (prof->module_start_load)
602 prof->module_start_load (prof->profiler, module);
604 case MONO_PROFILE_START_UNLOAD:
605 if (prof->module_start_unload)
606 prof->module_start_unload (prof->profiler, module);
608 case MONO_PROFILE_END_UNLOAD:
609 if (prof->module_end_unload)
610 prof->module_end_unload (prof->profiler, module);
613 g_assert_not_reached ();
619 mono_profiler_module_loaded (MonoImage *module, int result)
622 for (prof = prof_list; prof; prof = prof->next) {
623 if ((prof->events & MONO_PROFILE_MODULE_EVENTS) && prof->module_end_load)
624 prof->module_end_load (prof->profiler, module, result);
629 mono_profiler_class_event (MonoClass *klass, int code)
632 for (prof = prof_list; prof; prof = prof->next) {
633 if (!(prof->events & MONO_PROFILE_CLASS_EVENTS))
637 case MONO_PROFILE_START_LOAD:
638 if (prof->class_start_load)
639 prof->class_start_load (prof->profiler, klass);
641 case MONO_PROFILE_START_UNLOAD:
642 if (prof->class_start_unload)
643 prof->class_start_unload (prof->profiler, klass);
645 case MONO_PROFILE_END_UNLOAD:
646 if (prof->class_end_unload)
647 prof->class_end_unload (prof->profiler, klass);
650 g_assert_not_reached ();
656 mono_profiler_class_loaded (MonoClass *klass, int result)
659 for (prof = prof_list; prof; prof = prof->next) {
660 if ((prof->events & MONO_PROFILE_CLASS_EVENTS) && prof->class_end_load)
661 prof->class_end_load (prof->profiler, klass, result);
666 mono_profiler_appdomain_event (MonoDomain *domain, int code)
669 for (prof = prof_list; prof; prof = prof->next) {
670 if (!(prof->events & MONO_PROFILE_APPDOMAIN_EVENTS))
674 case MONO_PROFILE_START_LOAD:
675 if (prof->domain_start_load)
676 prof->domain_start_load (prof->profiler, domain);
678 case MONO_PROFILE_START_UNLOAD:
679 if (prof->domain_start_unload)
680 prof->domain_start_unload (prof->profiler, domain);
682 case MONO_PROFILE_END_UNLOAD:
683 if (prof->domain_end_unload)
684 prof->domain_end_unload (prof->profiler, domain);
687 g_assert_not_reached ();
693 mono_profiler_appdomain_loaded (MonoDomain *domain, int result)
696 for (prof = prof_list; prof; prof = prof->next) {
697 if ((prof->events & MONO_PROFILE_APPDOMAIN_EVENTS) && prof->domain_end_load)
698 prof->domain_end_load (prof->profiler, domain, result);
703 mono_profiler_shutdown (void)
706 for (prof = prof_list; prof; prof = prof->next) {
707 if (prof->shutdown_callback)
708 prof->shutdown_callback (prof->profiler);
711 mono_profiler_set_events (0);
715 mono_profiler_gc_heap_resize (gint64 new_size)
718 for (prof = prof_list; prof; prof = prof->next) {
719 if ((prof->events & MONO_PROFILE_GC) && prof->gc_heap_resize)
720 prof->gc_heap_resize (prof->profiler, new_size);
725 mono_profiler_gc_event (MonoGCEvent event, int generation)
728 for (prof = prof_list; prof; prof = prof->next) {
729 if ((prof->events & MONO_PROFILE_GC) && prof->gc_event)
730 prof->gc_event (prof->profiler, event, generation);
735 mono_profiler_gc_moves (void **objects, int num)
738 for (prof = prof_list; prof; prof = prof->next) {
739 if ((prof->events & MONO_PROFILE_GC_MOVES) && prof->gc_moves)
740 prof->gc_moves (prof->profiler, objects, num);
745 mono_profiler_gc_handle (int op, int type, uintptr_t handle, MonoObject *obj)
748 for (prof = prof_list; prof; prof = prof->next) {
749 if ((prof->events & MONO_PROFILE_GC_ROOTS) && prof->gc_handle)
750 prof->gc_handle (prof->profiler, op, type, handle, obj);
755 mono_profiler_install_gc (MonoProfileGCFunc callback, MonoProfileGCResizeFunc heap_resize_callback)
757 mono_gc_enable_events ();
760 prof_list->gc_event = callback;
761 prof_list->gc_heap_resize = heap_resize_callback;
765 * mono_profiler_install_gc_moves:
766 * @callback: callback function
768 * Install the @callback function that the GC will call when moving objects.
769 * The callback receives an array of pointers and the number of elements
770 * in the array. Every even element in the array is the original object location
771 * and the following odd element is the new location of the object in memory.
772 * So the number of elements argument will always be a multiple of 2.
773 * Since this callback happens during the GC, it is a restricted environment:
774 * no locks can be taken and the object pointers can be inspected only once
775 * the GC is finished (of course the original location pointers will not
776 * point to valid objects anymore).
779 mono_profiler_install_gc_moves (MonoProfileGCMoveFunc callback)
783 prof_list->gc_moves = callback;
787 * mono_profiler_install_gc_roots:
788 * @handle_callback: callback function
790 * Install the @handle_callback function that the GC will call when GC
791 * handles are created or destroyed.
792 * The callback receives an operation, which is either #MONO_PROFILER_GC_HANDLE_CREATED
793 * or #MONO_PROFILER_GC_HANDLE_DESTROYED, the handle type, the handle value and the
794 * object pointer, if present.
797 mono_profiler_install_gc_roots (MonoProfileGCHandleFunc handle_callback)
801 prof_list->gc_handle = handle_callback;
805 mono_profiler_install_runtime_initialized (MonoProfileFunc runtime_initialized_callback)
809 prof_list->runtime_initialized_event = runtime_initialized_callback;
813 mono_profiler_runtime_initialized (void) {
815 for (prof = prof_list; prof; prof = prof->next) {
816 if (prof->runtime_initialized_event)
817 prof->runtime_initialized_event (prof->profiler);
822 mono_profiler_install_code_chunk_new (MonoProfilerCodeChunkNew callback) {
825 prof_list->code_chunk_new = callback;
828 mono_profiler_code_chunk_new (gpointer chunk, int size) {
830 for (prof = prof_list; prof; prof = prof->next) {
831 if (prof->code_chunk_new)
832 prof->code_chunk_new (prof->profiler, chunk, size);
837 mono_profiler_install_code_chunk_destroy (MonoProfilerCodeChunkDestroy callback) {
840 prof_list->code_chunk_destroy = callback;
843 mono_profiler_code_chunk_destroy (gpointer chunk) {
845 for (prof = prof_list; prof; prof = prof->next) {
846 if (prof->code_chunk_destroy)
847 prof->code_chunk_destroy (prof->profiler, chunk);
852 mono_profiler_install_code_buffer_new (MonoProfilerCodeBufferNew callback) {
855 prof_list->code_buffer_new = callback;
859 mono_profiler_install_iomap (MonoProfileIomapFunc callback)
863 prof_list->iomap_cb = callback;
867 mono_profiler_code_buffer_new (gpointer buffer, int size, MonoProfilerCodeBufferType type, void *data) {
869 for (prof = prof_list; prof; prof = prof->next) {
870 if (prof->code_buffer_new)
871 prof->code_buffer_new (prof->profiler, buffer, size, type, data);
875 static GHashTable *coverage_hash = NULL;
877 MonoProfileCoverageInfo*
878 mono_profiler_coverage_alloc (MonoMethod *method, int entries)
880 MonoProfileCoverageInfo *res;
881 int instrument = FALSE;
884 for (prof = prof_list; prof; prof = prof->next) {
885 /* note that we call the filter on all the profilers even if just
886 * a single one would be enough to instrument a method
888 if (prof->coverage_filter_cb)
889 if (prof->coverage_filter_cb (prof->profiler, method))
895 mono_profiler_coverage_lock ();
897 coverage_hash = g_hash_table_new (NULL, NULL);
899 res = g_malloc0 (sizeof (MonoProfileCoverageInfo) + sizeof (void*) * 2 * entries);
901 res->entries = entries;
903 g_hash_table_insert (coverage_hash, method, res);
904 mono_profiler_coverage_unlock ();
909 /* safe only when the method antive code has been unloaded */
911 mono_profiler_coverage_free (MonoMethod *method)
913 MonoProfileCoverageInfo* info;
915 mono_profiler_coverage_lock ();
916 if (!coverage_hash) {
917 mono_profiler_coverage_unlock ();
921 info = g_hash_table_lookup (coverage_hash, method);
924 g_hash_table_remove (coverage_hash, method);
926 mono_profiler_coverage_unlock ();
930 * mono_profiler_coverage_get:
931 * @prof: The profiler handle, installed with mono_profiler_install
932 * @method: the method to gather information from.
933 * @func: A routine that will be called back with the results
935 * If the MONO_PROFILER_INS_COVERAGE flag was active during JIT compilation
936 * it is posisble to obtain coverage information about a give method.
938 * The function @func will be invoked repeatedly with instances of the
939 * MonoProfileCoverageEntry structure.
942 mono_profiler_coverage_get (MonoProfiler *prof, MonoMethod *method, MonoProfileCoverageFunc func)
944 MonoProfileCoverageInfo* info;
947 const unsigned char *start, *end, *cil_code;
948 MonoMethodHeader *header;
949 MonoProfileCoverageEntry entry;
950 MonoDebugMethodInfo *debug_minfo;
952 mono_profiler_coverage_lock ();
953 info = g_hash_table_lookup (coverage_hash, method);
954 mono_profiler_coverage_unlock ();
959 header = mono_method_get_header (method);
960 start = mono_method_header_get_code (header, &code_size, NULL);
961 debug_minfo = mono_debug_lookup_method (method);
963 end = start + code_size;
964 for (i = 0; i < info->entries; ++i) {
965 cil_code = info->data [i].cil_code;
966 if (cil_code && cil_code >= start && cil_code < end) {
968 offset = cil_code - start;
969 entry.iloffset = offset;
970 entry.method = method;
971 entry.counter = info->data [i].count;
972 entry.line = entry.col = 1;
973 entry.filename = NULL;
975 MonoDebugSourceLocation *location;
977 location = mono_debug_symfile_lookup_location (debug_minfo, offset);
979 entry.line = location->row;
980 entry.col = location->column;
981 entry.filename = fname = g_strdup (location->source_file);
982 mono_debug_free_source_location (location);
990 mono_metadata_free_mh (header);
993 typedef void (*ProfilerInitializer) (const char*);
994 #define INITIALIZER_NAME "mono_profiler_startup"
997 * mono_profiler_load:
998 * @desc: arguments to configure the profiler
1000 * Invoke this method to initialize the profiler. This will drive the
1001 * loading of the internal ("default") or any external profilers.
1003 * This routine is invoked by Mono's driver, but must be called manually
1004 * if you embed Mono into your application.
1007 mono_profiler_load (const char *desc)
1009 mono_gc_base_init ();
1011 #ifndef DISABLE_PROFILER
1012 if (!desc || (strcmp ("default", desc) == 0) || (strncmp (desc, "default:", 8) == 0)) {
1013 mono_profiler_install_simple (desc);
1022 MonoDl *pmodule = NULL;
1023 const char* col = strchr (desc, ':');
1030 mname = g_memdup (desc, col - desc + 1);
1031 mname [col - desc] = 0;
1033 mname = g_strdup (desc);
1035 libname = g_strdup_printf ("mono-profiler-%s", mname);
1038 while ((path = mono_dl_build_path (NULL, libname, &iter))) {
1040 pmodule = mono_dl_open (path, MONO_DL_LAZY, &err);
1042 ProfilerInitializer func;
1043 if ((err = mono_dl_symbol (pmodule, INITIALIZER_NAME, (gpointer *)&func))) {
1044 g_warning ("Cannot find initializer function %s in profiler module: %s (%s)", INITIALIZER_NAME, libname, err);
1055 g_warning ("Error loading profiler module '%s': %s", libname, err);