diff --git a/mono/eglib/ghashtable.c b/mono/eglib/ghashtable.c index 5329fab0cabc..5f49702b467f 100644 --- a/mono/eglib/ghashtable.c +++ b/mono/eglib/ghashtable.c @@ -48,8 +48,8 @@ struct _GHashTable { Slot **table; int table_size; int in_use; - int threshold; int last_rehash; + gboolean uses_default_hash_and_equality; GDestroyNotify value_destroy_func, key_destroy_func; }; @@ -119,6 +119,7 @@ g_hash_table_new (GHashFunc hash_func, GEqualFunc key_equal_func) hash->hash_func = hash_func; hash->key_equal_func = key_equal_func; + hash->uses_default_hash_and_equality = hash->hash_func == g_direct_hash && hash->key_equal_func == g_direct_equal; hash->table_size = g_spaced_primes_closest (1); hash->table = g_new0 (Slot *, hash->table_size); @@ -239,8 +240,7 @@ g_hash_table_insert_replace (GHashTable *hash, gpointer key, gpointer value, gbo sanity_check (hash); equal = hash->key_equal_func; - if (hash->in_use >= hash->threshold) - rehash (hash); + rehash (hash); hashcode = ((*hash->hash_func) (key)) % hash->table_size; for (s = hash->table [hashcode]; s != NULL; s = s->next){ @@ -348,6 +348,36 @@ g_hash_table_lookup_extended (GHashTable *hash, gconstpointer key, gpointer *ori } return FALSE; } +#ifdef G_OS_WIN32 + +#define OFFSET_MEMBER(type, base, member) ((gpointer)((gchar*)(base) + offsetof(type, member))) + +gpointer +g_hash_table_lookup_oop(GHashTable* hash, gconstpointer key, GReadPointerFunc read_pointer, GReadUInt32Func read_uint32) +{ + g_return_val_if_fail(hash != NULL, NULL); + // This is only safe if we are using the default hash/equality functions + g_return_val_if_fail(read_uint32(OFFSET_MEMBER(GHashTable, hash, uses_default_hash_and_equality)) != 0, NULL); + + gint32 table_size = read_uint32(OFFSET_MEMBER(GHashTable, hash, table_size)); + guint hashcode = g_direct_hash(key) % table_size; + + Slot** slots = read_pointer(OFFSET_MEMBER(GHashTable, hash, table)); + { + Slot* slot = read_pointer(slots + hashcode); + while (slot != NULL) + { + if (key == read_pointer(OFFSET_MEMBER(Slot, slot, key))) + return read_pointer(OFFSET_MEMBER(Slot, slot, value)); + + slot = read_pointer(OFFSET_MEMBER(Slot, slot, next)); + } + } + + return NULL; +} + +#endif void g_hash_table_foreach (GHashTable *hash, GHFunc func, gpointer user_data) diff --git a/mono/eglib/glib.h b/mono/eglib/glib.h index 6aee6c420823..5f4739ce2cf7 100644 --- a/mono/eglib/glib.h +++ b/mono/eglib/glib.h @@ -493,6 +493,11 @@ typedef void (*GDestroyNotify) (gpointer data); typedef guint (*GHashFunc) (gconstpointer key); typedef gboolean (*GEqualFunc) (gconstpointer a, gconstpointer b); typedef void (*GFreeFunc) (gpointer data); +#ifdef G_OS_WIN32 +/* oop support*/ +typedef gpointer (*GReadPointerFunc)(gconstpointer address); +typedef guint32 (*GReadUInt32Func) (gconstpointer address); +#endif /* * Lists @@ -630,6 +635,9 @@ gboolean g_hash_table_contains (GHashTable *hash, gconstpointer key); G_EXTERN_C // Used by MonoPosixHelper or MonoSupportW, at least. gpointer g_hash_table_lookup (GHashTable *hash, gconstpointer key); gboolean g_hash_table_lookup_extended (GHashTable *hash, gconstpointer key, gpointer *orig_key, gpointer *value); +#ifdef G_OS_WIN32 +gpointer g_hash_table_lookup_oop (GHashTable* hash, gconstpointer key, GReadPointerFunc read_pointer, GReadUInt32Func read_uint32); +#endif G_EXTERN_C // Used by MonoPosixHelper or MonoSupportW, at least. void g_hash_table_foreach (GHashTable *hash, GHFunc func, gpointer user_data); gpointer g_hash_table_find (GHashTable *hash, GHRFunc predicate, gpointer user_data); diff --git a/mono/metadata/oop.c b/mono/metadata/oop.c index 92036b11bfae..bcf1c1f3ce7a 100644 --- a/mono/metadata/oop.c +++ b/mono/metadata/oop.c @@ -53,6 +53,8 @@ typedef struct _MonoStackFrameDetails size_t assemblyNameLen; char* assemblyFileName; size_t assemblyFileNameLen; + gint32 ilOffset; + gint32 methodToken; } MonoStackFrameDetails; typedef gboolean(*ReadMemoryCallback)(void* buffer, gsize* read, const void* address, gsize size, void* userdata); @@ -134,6 +136,13 @@ gint32 read_dword(const void* address) return v; } +gint8 read_byte(const void* address) +{ + gint8 v = 0; + read_memory(&v, address, sizeof(v)); + return v; +} + GList* read_glist_next(GList* list) { return (GList*) read_pointer(OFFSET_MEMBER(GList, list, next)); } gpointer read_glist_data(GList* list) { return read_pointer(OFFSET_MEMBER(GList, list, data)); } @@ -372,6 +381,36 @@ oop_jit_info_table_find( return NULL; } +typedef struct { + MonoMemPool* mp; + GHashTable* method_hash; +} DebugDomainInfo; + +typedef struct { + const guint8* code_start; + guint32 code_size; + guint8 data[MONO_ZERO_LEN_ARRAY]; +} MonoDebugMethodAddress; + +static guint32 +read_leb128_oop(guint8* ptr, guint8** rptr) +{ + guint32 result = 0, shift = 0; + + while (TRUE) { + guint8 byte = read_byte(ptr); + ptr++; + + result |= (byte & 0x7f) << shift; + if ((byte & 0x80) == 0) + break; + shift += 7; + } + + *rptr = ptr; + return result; +} + MONO_API int mono_unity_oop_get_stack_frame_details( const MonoDomain* domain, @@ -435,6 +474,44 @@ mono_unity_oop_get_stack_frame_details( free(className); free(nsName); + frameDetails->methodToken = read_dword(OFFSET_MEMBER(MonoMethod, method, token)); + + // IL offset + DebugDomainInfo* debug_info = read_pointer(OFFSET_MEMBER(MonoDomain, domain, debug_info)); + if (debug_info != NULL) + { + guint8* code_start = read_pointer(OFFSET_MEMBER(MonoJitInfo, ji, code_start)); + int nativeOffset = (int)((guint8*)frameAddress - code_start); + GHashTable* method_hash = read_pointer(OFFSET_MEMBER(DebugDomainInfo, debug_info, method_hash)); + MonoDebugMethodAddress* address = g_hash_table_lookup_oop(method_hash, method, &read_pointer, &read_dword); + + if (address) + { + // reduced implementation of mono_debug_read_method + guint8* ptr = OFFSET_MEMBER(MonoDebugMethodAddress, address, data); + + // jit->prologue_end = read_leb128(ptr, &ptr); + read_leb128_oop(ptr, &ptr); + // jit->epilogue_begin = read_leb128(ptr, &ptr); + read_leb128_oop(ptr, &ptr); + // jit->num_line_numbers = read_leb128(ptr, &ptr); + guint32 num_line_numbers = read_leb128_oop(ptr, &ptr); + for (guint32 j = 0; j < num_line_numbers; j++) + { + gint32 il_offset = read_leb128_oop(ptr, &ptr); + gint32 native_offset = read_leb128_oop(ptr, &ptr); + if (nativeOffset >= native_offset) + { + frameDetails->ilOffset = il_offset; + } + else + { + break; + } + } + } + } + return TRUE; }