@@ -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
5860typedef 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+
137146GList * read_glist_next (GList * list ) { return (GList * ) read_pointer (OFFSET_MEMBER (GList , list , next )); }
138147gpointer 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+
375414MONO_API int
376415mono_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