-
Notifications
You must be signed in to change notification settings - Fork 521
Add IL offset and method token to stack frame details. #2130
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: unity-6000.3-mbe
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This allows us to perform the same hashing/equality operations when out of process. |
||
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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The rehash was always occurring, as |
||
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) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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) | ||
Comment on lines
+404
to
+405
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe this is variable length encoding of integer values. Thus small values could be contained within a single byte. Larger values two bytes, etc. |
||
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; | ||
} | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was only used in one place, but never updated.