Skip to content

Commit e947990

Browse files
authored
Merge pull request #2207 from Unity-Technologies/forward-port-oop-token-iloffset
[Forward-port] Add IL offset and method token to stack frame details.
2 parents 452383f + 4c2dab4 commit e947990

File tree

3 files changed

+118
-3
lines changed

3 files changed

+118
-3
lines changed

mono/eglib/ghashtable.c

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ struct _GHashTable {
4848
Slot **table;
4949
int table_size;
5050
int in_use;
51-
int threshold;
5251
int last_rehash;
52+
gboolean uses_default_hash_and_equality;
5353
GDestroyNotify value_destroy_func, key_destroy_func;
5454
};
5555

@@ -119,6 +119,7 @@ g_hash_table_new (GHashFunc hash_func, GEqualFunc key_equal_func)
119119

120120
hash->hash_func = hash_func;
121121
hash->key_equal_func = key_equal_func;
122+
hash->uses_default_hash_and_equality = hash->hash_func == g_direct_hash && hash->key_equal_func == g_direct_equal;
122123

123124
hash->table_size = g_spaced_primes_closest (1);
124125
hash->table = g_new0 (Slot *, hash->table_size);
@@ -239,8 +240,7 @@ g_hash_table_insert_replace (GHashTable *hash, gpointer key, gpointer value, gbo
239240
sanity_check (hash);
240241

241242
equal = hash->key_equal_func;
242-
if (hash->in_use >= hash->threshold)
243-
rehash (hash);
243+
rehash (hash);
244244

245245
hashcode = ((*hash->hash_func) (key)) % hash->table_size;
246246
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
348348
}
349349
return FALSE;
350350
}
351+
#ifdef G_OS_WIN32
352+
353+
#define OFFSET_MEMBER(type, base, member) ((gpointer)((gchar*)(base) + offsetof(type, member)))
354+
355+
gpointer
356+
g_hash_table_lookup_oop(GHashTable* hash, gconstpointer key, GReadPointerFunc read_pointer, GReadUInt32Func read_uint32)
357+
{
358+
g_return_val_if_fail(hash != NULL, NULL);
359+
// This is only safe if we are using the default hash/equality functions
360+
g_return_val_if_fail(read_uint32(OFFSET_MEMBER(GHashTable, hash, uses_default_hash_and_equality)) != 0, NULL);
361+
362+
gint32 table_size = read_uint32(OFFSET_MEMBER(GHashTable, hash, table_size));
363+
guint hashcode = g_direct_hash(key) % table_size;
364+
365+
Slot** slots = read_pointer(OFFSET_MEMBER(GHashTable, hash, table));
366+
{
367+
Slot* slot = read_pointer(slots + hashcode);
368+
while (slot != NULL)
369+
{
370+
if (key == read_pointer(OFFSET_MEMBER(Slot, slot, key)))
371+
return read_pointer(OFFSET_MEMBER(Slot, slot, value));
372+
373+
slot = read_pointer(OFFSET_MEMBER(Slot, slot, next));
374+
}
375+
}
376+
377+
return NULL;
378+
}
379+
380+
#endif
351381

352382
void
353383
g_hash_table_foreach (GHashTable *hash, GHFunc func, gpointer user_data)

mono/eglib/glib.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,11 @@ typedef void (*GDestroyNotify) (gpointer data);
493493
typedef guint (*GHashFunc) (gconstpointer key);
494494
typedef gboolean (*GEqualFunc) (gconstpointer a, gconstpointer b);
495495
typedef void (*GFreeFunc) (gpointer data);
496+
#ifdef G_OS_WIN32
497+
/* oop support*/
498+
typedef gpointer (*GReadPointerFunc)(gconstpointer address);
499+
typedef guint32 (*GReadUInt32Func) (gconstpointer address);
500+
#endif
496501

497502
/*
498503
* Lists
@@ -630,6 +635,9 @@ gboolean g_hash_table_contains (GHashTable *hash, gconstpointer key);
630635
G_EXTERN_C // Used by MonoPosixHelper or MonoSupportW, at least.
631636
gpointer g_hash_table_lookup (GHashTable *hash, gconstpointer key);
632637
gboolean g_hash_table_lookup_extended (GHashTable *hash, gconstpointer key, gpointer *orig_key, gpointer *value);
638+
#ifdef G_OS_WIN32
639+
gpointer g_hash_table_lookup_oop (GHashTable* hash, gconstpointer key, GReadPointerFunc read_pointer, GReadUInt32Func read_uint32);
640+
#endif
633641
G_EXTERN_C // Used by MonoPosixHelper or MonoSupportW, at least.
634642
void g_hash_table_foreach (GHashTable *hash, GHFunc func, gpointer user_data);
635643
gpointer g_hash_table_find (GHashTable *hash, GHRFunc predicate, gpointer user_data);

mono/metadata/oop.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ typedef struct _MonoStackFrameDetails
5353
size_t assemblyNameLen;
5454
char* assemblyFileName;
5555
size_t assemblyFileNameLen;
56+
gint32 ilOffset;
57+
gint32 methodToken;
5658
} MonoStackFrameDetails;
5759

5860
typedef gboolean(*ReadMemoryCallback)(void* buffer, gsize* read, const void* address, gsize size, void* userdata);
@@ -134,6 +136,13 @@ gint32 read_dword(const void* address)
134136
return v;
135137
}
136138

139+
gint8 read_byte(const void* address)
140+
{
141+
gint8 v = 0;
142+
read_memory(&v, address, sizeof(v));
143+
return v;
144+
}
145+
137146
GList* read_glist_next(GList* list) { return (GList*) read_pointer(OFFSET_MEMBER(GList, list, next)); }
138147
gpointer read_glist_data(GList* list) { return read_pointer(OFFSET_MEMBER(GList, list, data)); }
139148

@@ -372,6 +381,36 @@ oop_jit_info_table_find(
372381
return NULL;
373382
}
374383

384+
typedef struct {
385+
MonoMemPool* mp;
386+
GHashTable* method_hash;
387+
} DebugDomainInfo;
388+
389+
typedef struct {
390+
const guint8* code_start;
391+
guint32 code_size;
392+
guint8 data[MONO_ZERO_LEN_ARRAY];
393+
} MonoDebugMethodAddress;
394+
395+
static guint32
396+
read_leb128_oop(guint8* ptr, guint8** rptr)
397+
{
398+
guint32 result = 0, shift = 0;
399+
400+
while (TRUE) {
401+
guint8 byte = read_byte(ptr);
402+
ptr++;
403+
404+
result |= (byte & 0x7f) << shift;
405+
if ((byte & 0x80) == 0)
406+
break;
407+
shift += 7;
408+
}
409+
410+
*rptr = ptr;
411+
return result;
412+
}
413+
375414
MONO_API int
376415
mono_unity_oop_get_stack_frame_details(
377416
const MonoDomain* domain,
@@ -435,6 +474,44 @@ mono_unity_oop_get_stack_frame_details(
435474
free(className);
436475
free(nsName);
437476

477+
frameDetails->methodToken = read_dword(OFFSET_MEMBER(MonoMethod, method, token));
478+
479+
// IL offset
480+
DebugDomainInfo* debug_info = read_pointer(OFFSET_MEMBER(MonoDomain, domain, debug_info));
481+
if (debug_info != NULL)
482+
{
483+
guint8* code_start = read_pointer(OFFSET_MEMBER(MonoJitInfo, ji, code_start));
484+
int nativeOffset = (int)((guint8*)frameAddress - code_start);
485+
GHashTable* method_hash = read_pointer(OFFSET_MEMBER(DebugDomainInfo, debug_info, method_hash));
486+
MonoDebugMethodAddress* address = g_hash_table_lookup_oop(method_hash, method, &read_pointer, &read_dword);
487+
488+
if (address)
489+
{
490+
// reduced implementation of mono_debug_read_method
491+
guint8* ptr = OFFSET_MEMBER(MonoDebugMethodAddress, address, data);
492+
493+
// jit->prologue_end = read_leb128(ptr, &ptr);
494+
read_leb128_oop(ptr, &ptr);
495+
// jit->epilogue_begin = read_leb128(ptr, &ptr);
496+
read_leb128_oop(ptr, &ptr);
497+
// jit->num_line_numbers = read_leb128(ptr, &ptr);
498+
guint32 num_line_numbers = read_leb128_oop(ptr, &ptr);
499+
for (guint32 j = 0; j < num_line_numbers; j++)
500+
{
501+
gint32 il_offset = read_leb128_oop(ptr, &ptr);
502+
gint32 native_offset = read_leb128_oop(ptr, &ptr);
503+
if (nativeOffset >= native_offset)
504+
{
505+
frameDetails->ilOffset = il_offset;
506+
}
507+
else
508+
{
509+
break;
510+
}
511+
}
512+
}
513+
}
514+
438515
return TRUE;
439516
}
440517

0 commit comments

Comments
 (0)