2 * debug-mono-symfile.c:
5 * Mono Project (http://www.mono-project.com)
7 * Copyright (C) 2005-2008 Novell, Inc. (http://www.novell.com)
8 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
16 #ifdef HAVE_SYS_PARAM_H
17 #include <sys/param.h>
20 #include <mono/metadata/metadata.h>
21 #include <mono/metadata/tabledefs.h>
22 #include <mono/metadata/tokentype.h>
23 #include <mono/metadata/appdomain.h>
24 #include <mono/metadata/exception.h>
25 #include <mono/metadata/debug-helpers.h>
26 #include <mono/metadata/mono-debug.h>
27 #include <mono/metadata/debug-mono-symfile.h>
28 #include <mono/metadata/mono-debug-debugger.h>
29 #include <mono/metadata/mono-endian.h>
30 #include <mono/metadata/metadata-internals.h>
31 #include <mono/metadata/class-internals.h>
32 #include <mono/utils/mono-mmap.h>
33 #include <mono/utils/bsearch.h>
40 #define RANGE_TABLE_CHUNK_SIZE 256
41 #define CLASS_TABLE_CHUNK_SIZE 256
42 #define TYPE_TABLE_PTR_CHUNK_SIZE 256
43 #define TYPE_TABLE_CHUNK_SIZE 65536
45 struct _MonoSymbolFile
{
46 const uint8_t *raw_contents
;
47 int raw_contents_size
;
48 void *raw_contents_handle
;
52 GHashTable
*method_hash
;
53 GHashTable
*source_hash
;
54 MonoSymbolFileOffsetTable
*offset_table
;
55 gboolean was_loaded_from_memory
;
59 free_method_info (MonoDebugMethodInfo
*minfo
)
65 free_source_info (MonoDebugSourceInfo
*sinfo
)
67 g_free (sinfo
->source_file
);
74 load_symfile (MonoDebugHandle
*handle
, MonoSymbolFile
*symfile
, mono_bool in_the_debugger
)
76 const char *ptr
, *start
;
81 ptr
= start
= (const char*)symfile
->raw_contents
;
86 ptr
+= sizeof(uint64_t);
87 if (magic
!= MONO_SYMBOL_FILE_MAGIC
) {
89 g_warning ("Symbol file %s is not a mono symbol file", symfile
->filename
);
94 ptr
+= sizeof(uint32_t);
96 ptr
+= sizeof(uint32_t);
99 * 50.0 is the frozen version for Mono 2.0.
101 * Nobody except me (Martin) is allowed to check the minor version.
103 if (major
!= MONO_SYMBOL_FILE_MAJOR_VERSION
) {
104 if (!in_the_debugger
)
105 g_warning ("Symbol file %s has incorrect version (expected %d.%d, got %d)",
106 symfile
->filename
, MONO_SYMBOL_FILE_MAJOR_VERSION
,
107 MONO_SYMBOL_FILE_MINOR_VERSION
, major
);
111 guid
= mono_guid_to_string ((const uint8_t *) ptr
);
114 if (strcmp (handle
->image
->guid
, guid
)) {
115 if (!in_the_debugger
)
116 g_warning ("Symbol file %s doesn't match image %s", symfile
->filename
,
123 symfile
->major_version
= major
;
124 symfile
->minor_version
= minor
;
126 symfile
->offset_table
= (MonoSymbolFileOffsetTable
*) ptr
;
128 symfile
->method_hash
= g_hash_table_new_full (
129 NULL
, NULL
, NULL
, (GDestroyNotify
) free_method_info
);
131 symfile
->source_hash
= g_hash_table_new_full (
132 NULL
, NULL
, NULL
, (GDestroyNotify
) free_source_info
);
139 mono_debug_open_mono_symbols (MonoDebugHandle
*handle
, const uint8_t *raw_contents
,
140 int size
, gboolean in_the_debugger
)
142 MonoSymbolFile
*symfile
;
144 mono_debugger_lock ();
145 symfile
= g_new0 (MonoSymbolFile
, 1);
147 if (raw_contents
!= NULL
) {
149 symfile
->raw_contents_size
= size
;
150 symfile
->raw_contents
= p
= g_malloc (size
);
151 memcpy (p
, raw_contents
, size
);
152 symfile
->filename
= g_strdup_printf ("LoadedFromMemory");
153 symfile
->was_loaded_from_memory
= TRUE
;
156 symfile
->filename
= g_strdup_printf ("%s.mdb", mono_image_get_filename (handle
->image
));
157 symfile
->was_loaded_from_memory
= FALSE
;
158 if ((f
= mono_file_map_open (symfile
->filename
))) {
159 symfile
->raw_contents_size
= mono_file_map_size (f
);
160 if (symfile
->raw_contents_size
== 0) {
161 if (!in_the_debugger
)
162 g_warning ("stat of %s failed: %s",
163 symfile
->filename
, g_strerror (errno
));
165 symfile
->raw_contents
= mono_file_map (symfile
->raw_contents_size
, MONO_MMAP_READ
|MONO_MMAP_PRIVATE
, mono_file_map_fd (f
), 0, &symfile
->raw_contents_handle
);
168 mono_file_map_close (f
);
172 if (load_symfile (handle
, symfile
, in_the_debugger
)) {
173 mono_debugger_unlock ();
175 } else if (!in_the_debugger
) {
176 mono_debug_close_mono_symbol_file (symfile
);
177 mono_debugger_unlock ();
181 mono_debugger_unlock ();
186 mono_debug_close_mono_symbol_file (MonoSymbolFile
*symfile
)
191 mono_debugger_lock ();
192 if (symfile
->method_hash
)
193 g_hash_table_destroy (symfile
->method_hash
);
195 if (symfile
->raw_contents
) {
196 if (symfile
->was_loaded_from_memory
)
197 g_free ((gpointer
)symfile
->raw_contents
);
199 mono_file_unmap ((gpointer
) symfile
->raw_contents
, symfile
->raw_contents_handle
);
202 if (symfile
->filename
)
203 g_free (symfile
->filename
);
205 mono_debugger_unlock ();
209 mono_debug_symfile_is_loaded (MonoSymbolFile
*symfile
)
211 return symfile
&& symfile
->offset_table
;
216 read_leb128 (const uint8_t *ptr
, const uint8_t **rptr
)
225 ret
= ret
| ((b
& 0x7f) << shift
);
227 } while ((b
& 0x80) == 0x80);
236 read_string (const uint8_t *ptr
, const uint8_t **endp
)
239 int len
= read_leb128 (ptr
, &ptr
);
241 s
= g_filename_from_utf8 ((const char *) ptr
, len
, NULL
, NULL
, NULL
);
249 MonoSymbolFile
*symfile
;
250 int line_base
, line_range
, max_address_incr
;
252 uint32_t last_line
, last_file
, last_offset
;
254 int line
, file
, offset
;
259 check_line (StatementMachine
*stm
, int offset
, MonoDebugSourceLocation
**location
)
261 gchar
*source_file
= NULL
;
263 if (stm
->offset
<= offset
) {
264 stm
->last_offset
= stm
->offset
;
265 stm
->last_file
= stm
->file
;
266 if (stm
->line
!= 0xfeefee)
267 stm
->last_line
= stm
->line
;
271 if (stm
->last_file
) {
272 int offset
= read32(&(stm
->symfile
->offset_table
->_source_table_offset
)) +
273 (stm
->last_file
- 1) * sizeof (MonoSymbolFileSourceEntry
);
274 MonoSymbolFileSourceEntry
*se
= (MonoSymbolFileSourceEntry
*)
275 (stm
->symfile
->raw_contents
+ offset
);
277 source_file
= read_string (stm
->symfile
->raw_contents
+ read32(&(se
->_data_offset
)), NULL
);
280 if (stm
->last_line
== 0) {
282 * The IL offset is less than the first IL offset which has a corresponding
289 *location
= g_new0 (MonoDebugSourceLocation
, 1);
290 (*location
)->source_file
= source_file
;
291 (*location
)->row
= stm
->last_line
;
292 (*location
)->il_offset
= stm
->last_offset
;
297 * mono_debug_symfile_lookup_location:
298 * @minfo: A `MonoDebugMethodInfo' which can be retrieved by
299 * mono_debug_lookup_method().
300 * @offset: IL offset within the corresponding method's CIL code.
302 * This function is similar to mono_debug_lookup_location(), but we
303 * already looked up the method and also already did the
304 * `native address -> IL offset' mapping.
306 MonoDebugSourceLocation
*
307 mono_debug_symfile_lookup_location (MonoDebugMethodInfo
*minfo
, uint32_t offset
)
309 MonoDebugSourceLocation
*location
= NULL
;
310 MonoSymbolFile
*symfile
;
311 const unsigned char *ptr
;
312 StatementMachine stm
;
314 #define DW_LNS_copy 1
315 #define DW_LNS_advance_pc 2
316 #define DW_LNS_advance_line 3
317 #define DW_LNS_set_file 4
318 #define DW_LNS_const_add_pc 8
320 #define DW_LNE_end_sequence 1
321 #define DW_LNE_MONO_negate_is_hidden 0x40
323 #define DW_LNE_MONO__extensions_start 0x40
324 #define DW_LNE_MONO__extensions_end 0x7f
326 if ((symfile
= minfo
->handle
->symfile
) == NULL
)
329 stm
.line_base
= read32 (&symfile
->offset_table
->_line_number_table_line_base
);
330 stm
.line_range
= read32 (&symfile
->offset_table
->_line_number_table_line_range
);
331 stm
.opcode_base
= (uint8_t) read32 (&symfile
->offset_table
->_line_number_table_opcode_base
);
332 stm
.max_address_incr
= (255 - stm
.opcode_base
) / stm
.line_range
;
334 mono_debugger_lock ();
336 ptr
= symfile
->raw_contents
+ minfo
->lnt_offset
;
338 stm
.symfile
= symfile
;
339 stm
.offset
= stm
.last_offset
= 0;
345 stm
.is_hidden
= FALSE
;
348 uint8_t opcode
= *ptr
++;
351 uint8_t size
= *ptr
++;
352 const unsigned char *end_ptr
= ptr
+ size
;
356 if (opcode
== DW_LNE_end_sequence
) {
357 if (check_line (&stm
, -1, &location
))
360 } else if (opcode
== DW_LNE_MONO_negate_is_hidden
) {
361 stm
.is_hidden
= !stm
.is_hidden
;
362 } else if ((opcode
>= DW_LNE_MONO__extensions_start
) &&
363 (opcode
<= DW_LNE_MONO__extensions_end
)) {
364 ; // reserved for future extensions
366 g_warning ("Unknown extended opcode %x in LNT", opcode
);
371 } else if (opcode
< stm
.opcode_base
) {
374 if (check_line (&stm
, offset
, &location
))
377 case DW_LNS_advance_pc
:
378 stm
.offset
+= read_leb128 (ptr
, &ptr
);
380 case DW_LNS_advance_line
:
381 stm
.line
+= read_leb128 (ptr
, &ptr
);
383 case DW_LNS_set_file
:
384 stm
.file
= read_leb128 (ptr
, &ptr
);
386 case DW_LNS_const_add_pc
:
387 stm
.offset
+= stm
.max_address_incr
;
390 g_warning ("Unknown standard opcode %x in LNT", opcode
);
394 opcode
-= stm
.opcode_base
;
396 stm
.offset
+= opcode
/ stm
.line_range
;
397 stm
.line
+= stm
.line_base
+ (opcode
% stm
.line_range
);
399 if (check_line (&stm
, offset
, &location
))
405 mono_debugger_unlock ();
409 mono_debugger_unlock ();
414 add_line (StatementMachine
*stm
, GPtrArray
*il_offset_array
, GPtrArray
*line_number_array
, GPtrArray
*source_file_array
, GPtrArray
*hidden_array
)
416 g_ptr_array_add (il_offset_array
, GUINT_TO_POINTER (stm
->offset
));
417 g_ptr_array_add (line_number_array
, GUINT_TO_POINTER (stm
->line
));
418 g_ptr_array_add (source_file_array
, GUINT_TO_POINTER (stm
->file
));
419 g_ptr_array_add (hidden_array
, GUINT_TO_POINTER (stm
->is_hidden
|| stm
->line
<= 0));
421 if (!stm
->is_hidden
&& !stm
->first_file
)
422 stm
->first_file
= stm
->file
;
426 * mono_debug_symfile_free_location:
428 * Free a MonoDebugSourceLocation returned by
429 * mono_debug_symfile_lookup_location
432 mono_debug_symfile_free_location (MonoDebugSourceLocation
*location
)
434 g_free (location
->source_file
);
439 * LOCKING: Assumes the debugger lock is held.
441 static MonoDebugSourceInfo
*
442 get_source_info (MonoSymbolFile
*symfile
, int index
)
444 MonoDebugSourceInfo
*info
;
446 info
= g_hash_table_lookup (symfile
->source_hash
, GUINT_TO_POINTER (index
));
448 int offset
= read32(&(symfile
->offset_table
->_source_table_offset
)) +
449 (index
- 1) * sizeof (MonoSymbolFileSourceEntry
);
450 MonoSymbolFileSourceEntry
*se
= (MonoSymbolFileSourceEntry
*)
451 (symfile
->raw_contents
+ offset
);
452 const uint8_t *ptr
= symfile
->raw_contents
+ read32(&(se
->_data_offset
));
454 info
= g_new0 (MonoDebugSourceInfo
, 1);
455 info
->source_file
= read_string (ptr
, &ptr
);
456 info
->guid
= g_malloc0 (16);
457 memcpy (info
->guid
, ptr
, 16);
459 info
->hash
= g_malloc0 (16);
460 memcpy (info
->hash
, ptr
, 16);
462 g_hash_table_insert (symfile
->source_hash
, GUINT_TO_POINTER (index
), info
);
468 LNT_FLAG_HAS_COLUMN_INFO
= 1 << 1,
469 LNT_FLAG_HAS_END_INFO
= 1 << 2,
470 } LineNumberTableFlags
;
472 static LineNumberTableFlags
473 method_get_lnt_flags (MonoDebugMethodInfo
*minfo
)
475 MonoSymbolFile
*symfile
;
476 const unsigned char *ptr
;
479 if ((symfile
= minfo
->handle
->symfile
) == NULL
)
482 ptr
= symfile
->raw_contents
+ minfo
->data_offset
;
484 /* Has to read 'flags' which is preceeded by a bunch of other data */
485 /* compile_unit_index */
486 read_leb128 (ptr
, &ptr
);
487 /* local variable table offset */
488 read_leb128 (ptr
, &ptr
);
490 read_leb128 (ptr
, &ptr
);
491 /* code block table offset */
492 read_leb128 (ptr
, &ptr
);
493 /* scope variable table offset */
494 read_leb128 (ptr
, &ptr
);
495 /* real name offset */
496 read_leb128 (ptr
, &ptr
);
498 flags
= read_leb128 (ptr
, &ptr
);
503 * mono_debug_symfile_get_line_numbers_full:
505 * On return, SOURCE_FILE_LIST will point to a GPtrArray of MonoDebugSourceFile
506 * structures, and SOURCE_FILES will contain indexes into this array.
507 * The MonoDebugSourceFile structures are owned by this module.
510 mono_debug_symfile_get_line_numbers_full (MonoDebugMethodInfo
*minfo
, char **source_file
, GPtrArray
**source_file_list
, int *n_il_offsets
, int **il_offsets
, int **line_numbers
, int **column_numbers
, int **source_files
, int **end_line_numbers
, int **end_column_numbers
)
512 // FIXME: Unify this with mono_debug_symfile_lookup_location
513 MonoSymbolFile
*symfile
;
514 const unsigned char *ptr
;
515 StatementMachine stm
;
517 LineNumberTableFlags flags
;
518 GPtrArray
*il_offset_array
, *line_number_array
, *source_file_array
, *hidden_array
;
519 gboolean has_column_info
, has_end_info
;
520 gboolean column_info_read
= FALSE
;
522 if (source_file_list
)
523 *source_file_list
= NULL
;
529 *source_files
= NULL
;
533 *line_numbers
= NULL
;
535 *column_numbers
= NULL
;
536 if (end_line_numbers
)
537 *end_line_numbers
= NULL
;
538 if (end_column_numbers
)
539 *end_column_numbers
= NULL
;
541 if ((symfile
= minfo
->handle
->symfile
) == NULL
)
544 flags
= method_get_lnt_flags (minfo
);
545 has_column_info
= (flags
& LNT_FLAG_HAS_COLUMN_INFO
) > 0;
546 has_end_info
= (flags
& LNT_FLAG_HAS_END_INFO
) > 0;
548 il_offset_array
= g_ptr_array_new ();
549 line_number_array
= g_ptr_array_new ();
550 source_file_array
= g_ptr_array_new ();
551 hidden_array
= g_ptr_array_new();
553 stm
.line_base
= read32 (&symfile
->offset_table
->_line_number_table_line_base
);
554 stm
.line_range
= read32 (&symfile
->offset_table
->_line_number_table_line_range
);
555 stm
.opcode_base
= (uint8_t) read32 (&symfile
->offset_table
->_line_number_table_opcode_base
);
556 stm
.max_address_incr
= (255 - stm
.opcode_base
) / stm
.line_range
;
558 mono_debugger_lock ();
560 ptr
= symfile
->raw_contents
+ minfo
->lnt_offset
;
562 stm
.symfile
= symfile
;
563 stm
.offset
= stm
.last_offset
= 0;
569 stm
.is_hidden
= FALSE
;
572 uint8_t opcode
= *ptr
++;
575 uint8_t size
= *ptr
++;
576 const unsigned char *end_ptr
= ptr
+ size
;
580 if (opcode
== DW_LNE_end_sequence
) {
581 if (il_offset_array
->len
== 0)
585 } else if (opcode
== DW_LNE_MONO_negate_is_hidden
) {
586 stm
.is_hidden
= !stm
.is_hidden
;
587 } else if ((opcode
>= DW_LNE_MONO__extensions_start
) &&
588 (opcode
<= DW_LNE_MONO__extensions_end
)) {
589 ; // reserved for future extensions
591 g_warning ("Unknown extended opcode %x in LNT", opcode
);
596 } else if (opcode
< stm
.opcode_base
) {
599 add_line (&stm
, il_offset_array
, line_number_array
, source_file_array
, hidden_array
);
601 case DW_LNS_advance_pc
:
602 stm
.offset
+= read_leb128 (ptr
, &ptr
);
604 case DW_LNS_advance_line
:
605 stm
.line
+= read_leb128 (ptr
, &ptr
);
607 case DW_LNS_set_file
:
608 stm
.file
= read_leb128 (ptr
, &ptr
);
610 case DW_LNS_const_add_pc
:
611 stm
.offset
+= stm
.max_address_incr
;
614 g_warning ("Unknown standard opcode %x in LNT", opcode
);
615 g_assert_not_reached ();
618 opcode
-= stm
.opcode_base
;
620 stm
.offset
+= opcode
/ stm
.line_range
;
621 stm
.line
+= stm
.line_base
+ (opcode
% stm
.line_range
);
623 add_line (&stm
, il_offset_array
, line_number_array
, source_file_array
, hidden_array
);
627 if (!stm
.file
&& stm
.first_file
)
628 stm
.file
= stm
.first_file
;
630 if (stm
.file
&& source_file
) {
631 int offset
= read32(&(stm
.symfile
->offset_table
->_source_table_offset
)) +
632 (stm
.file
- 1) * sizeof (MonoSymbolFileSourceEntry
);
633 MonoSymbolFileSourceEntry
*se
= (MonoSymbolFileSourceEntry
*)
634 (stm
.symfile
->raw_contents
+ offset
);
637 *source_file
= read_string (stm
.symfile
->raw_contents
+ read32(&(se
->_data_offset
)), NULL
);
640 if (source_file_list
) {
641 int file
, last_file
= 0;
643 *source_file_list
= g_ptr_array_new ();
645 *source_files
= g_malloc (il_offset_array
->len
* sizeof (int));
647 for (i
= 0; i
< il_offset_array
->len
; ++i
) {
648 file
= GPOINTER_TO_UINT (g_ptr_array_index (source_file_array
, i
));
649 if (file
&& file
!= last_file
) {
650 MonoDebugSourceInfo
*info
= get_source_info (symfile
, file
);
652 g_ptr_array_add (*source_file_list
, info
);
656 (*source_files
) [i
] = (*source_file_list
)->len
- 1;
658 if ((*source_file_list
)->len
== 0 && stm
.file
) {
659 MonoDebugSourceInfo
*info
= get_source_info (symfile
, stm
.file
);
661 g_ptr_array_add (*source_file_list
, info
);
666 *n_il_offsets
= il_offset_array
->len
;
667 for (i
= 0; i
< il_offset_array
->len
; i
++) {
668 if (GPOINTER_TO_UINT (g_ptr_array_index (hidden_array
, i
))) {
673 if (il_offsets
&& line_numbers
) {
674 *il_offsets
= g_malloc (*n_il_offsets
* sizeof (int));
675 *line_numbers
= g_malloc (*n_il_offsets
* sizeof (int));
677 for (i
= 0; i
< il_offset_array
->len
; ++i
) {
678 if (!GPOINTER_TO_UINT (g_ptr_array_index (hidden_array
, i
))) {
679 (*il_offsets
)[j
] = GPOINTER_TO_UINT (g_ptr_array_index (il_offset_array
, i
));
680 (*line_numbers
)[j
] = GPOINTER_TO_UINT (g_ptr_array_index (line_number_array
, i
));
686 if (column_numbers
&& has_column_info
) {
687 column_info_read
= TRUE
;
688 *column_numbers
= g_malloc (*n_il_offsets
* sizeof (int));
690 for (i
= 0; i
< il_offset_array
->len
; ++i
) {
691 int column
= read_leb128 (ptr
, &ptr
);
692 if (!GPOINTER_TO_UINT (g_ptr_array_index (hidden_array
, i
))) {
693 (*column_numbers
) [j
] = column
;
699 if (has_end_info
&& end_line_numbers
) {
700 g_assert (end_column_numbers
);
701 *end_line_numbers
= g_malloc (*n_il_offsets
* sizeof (int));
702 *end_column_numbers
= g_malloc (*n_il_offsets
* sizeof (int));
703 if (has_column_info
&& !column_info_read
) {
704 for (i
= 0; i
< il_offset_array
->len
; ++i
)
705 read_leb128 (ptr
, &ptr
);
708 for (i
= 0; i
< il_offset_array
->len
; ++i
) {
709 int end_row
, end_column
= -1;
711 end_row
= read_leb128 (ptr
, &ptr
);
712 if (end_row
!= 0xffffff) {
713 end_row
+= GPOINTER_TO_UINT (g_ptr_array_index (line_number_array
, i
));
714 end_column
= read_leb128 (ptr
, &ptr
);
715 if (!GPOINTER_TO_UINT (g_ptr_array_index (hidden_array
, i
))) {
716 (*end_line_numbers
)[j
] = end_row
;
717 (*end_column_numbers
)[j
] = end_column
;
724 g_ptr_array_free (il_offset_array
, TRUE
);
725 g_ptr_array_free (line_number_array
, TRUE
);
726 g_ptr_array_free (hidden_array
, TRUE
);
728 mono_debugger_unlock ();
733 * mono_debug_symfile_get_line_numbers:
735 * All the output parameters can be NULL.
738 mono_debug_symfile_get_line_numbers (MonoDebugMethodInfo
*minfo
, char **source_file
, int *n_il_offsets
, int **il_offsets
, int **line_numbers
)
740 mono_debug_symfile_get_line_numbers_full (minfo
, source_file
, NULL
, n_il_offsets
, il_offsets
, line_numbers
, NULL
, NULL
, NULL
, NULL
);
744 _mono_debug_address_from_il_offset (MonoDebugMethodJitInfo
*jit
, uint32_t il_offset
)
748 if (!jit
|| !jit
->line_numbers
)
751 for (i
= jit
->num_line_numbers
- 1; i
>= 0; i
--) {
752 MonoDebugLineNumberEntry lne
= jit
->line_numbers
[i
];
754 if (lne
.il_offset
<= il_offset
)
755 return lne
.native_offset
;
762 compare_method (const void *key
, const void *object
)
764 uint32_t token
= GPOINTER_TO_UINT (key
);
765 MonoSymbolFileMethodEntry
*me
= (MonoSymbolFileMethodEntry
*)object
;
767 return token
- read32(&(me
->_token
));
770 MonoDebugMethodInfo
*
771 mono_debug_symfile_lookup_method (MonoDebugHandle
*handle
, MonoMethod
*method
)
773 MonoSymbolFileMethodEntry
*first_ie
, *ie
;
774 MonoDebugMethodInfo
*minfo
;
775 MonoSymbolFile
*symfile
= handle
->symfile
;
777 if (!symfile
->method_hash
)
780 if (handle
->image
!= mono_class_get_image (mono_method_get_class (method
)))
783 mono_debugger_lock ();
785 minfo
= g_hash_table_lookup (symfile
->method_hash
, method
);
787 mono_debugger_unlock ();
791 first_ie
= (MonoSymbolFileMethodEntry
*)
792 (symfile
->raw_contents
+ read32(&(symfile
->offset_table
->_method_table_offset
)));
794 ie
= mono_binary_search (GUINT_TO_POINTER (mono_method_get_token (method
)), first_ie
,
795 read32(&(symfile
->offset_table
->_method_count
)),
796 sizeof (MonoSymbolFileMethodEntry
), compare_method
);
799 mono_debugger_unlock ();
803 minfo
= g_new0 (MonoDebugMethodInfo
, 1);
804 minfo
->index
= (ie
- first_ie
) + 1;
805 minfo
->method
= method
;
806 minfo
->handle
= handle
;
808 minfo
->data_offset
= read32 (&(ie
->_data_offset
));
809 minfo
->lnt_offset
= read32 (&(ie
->_line_number_table
));
811 g_hash_table_insert (symfile
->method_hash
, method
, minfo
);
813 mono_debugger_unlock ();
818 * mono_debug_symfile_lookup_locals:
820 * Return information about the local variables of MINFO from the symbol file.
821 * Return NULL if no information can be found.
822 * The result should be freed using mono_debug_symfile_free_locals ().
825 mono_debug_symfile_lookup_locals (MonoDebugMethodInfo
*minfo
)
827 MonoSymbolFile
*symfile
= minfo
->handle
->symfile
;
829 int i
, len
, compile_unit_index
, locals_offset
, num_locals
, block_index
;
830 int namespace_id
, code_block_table_offset
;
831 MonoDebugLocalsInfo
*res
;
836 p
= symfile
->raw_contents
+ minfo
->data_offset
;
838 compile_unit_index
= read_leb128 (p
, &p
);
839 locals_offset
= read_leb128 (p
, &p
);
840 namespace_id
= read_leb128 (p
, &p
);
841 code_block_table_offset
= read_leb128 (p
, &p
);
843 res
= g_new0 (MonoDebugLocalsInfo
, 1);
845 p
= symfile
->raw_contents
+ code_block_table_offset
;
846 res
->num_blocks
= read_leb128 (p
, &p
);
847 res
->code_blocks
= g_new0 (MonoDebugCodeBlock
, res
->num_blocks
);
848 for (i
= 0; i
< res
->num_blocks
; ++i
) {
849 res
->code_blocks
[i
].type
= read_leb128 (p
, &p
);
850 res
->code_blocks
[i
].parent
= read_leb128 (p
, &p
);
851 res
->code_blocks
[i
].start_offset
= read_leb128 (p
, &p
);
852 res
->code_blocks
[i
].end_offset
= read_leb128 (p
, &p
);
855 p
= symfile
->raw_contents
+ locals_offset
;
856 num_locals
= read_leb128 (p
, &p
);
858 res
->num_locals
= num_locals
;
859 res
->locals
= g_new0 (MonoDebugLocalVar
, num_locals
);
861 for (i
= 0; i
< num_locals
; ++i
) {
862 res
->locals
[i
].index
= read_leb128 (p
, &p
);
863 len
= read_leb128 (p
, &p
);
864 res
->locals
[i
].name
= g_malloc (len
+ 1);
865 memcpy (res
->locals
[i
].name
, p
, len
);
866 res
->locals
[i
].name
[len
] = '\0';
868 block_index
= read_leb128 (p
, &p
);
869 if (block_index
>= 1 && block_index
<= res
->num_blocks
)
870 res
->locals
[i
].block
= &res
->code_blocks
[block_index
- 1];
877 * mono_debug_symfile_free_locals:
879 * Free all the data allocated by mono_debug_symfile_lookup_locals ().
882 mono_debug_symfile_free_locals (MonoDebugLocalsInfo
*info
)
886 for (i
= 0; i
< info
->num_locals
; ++i
)
887 g_free (info
->locals
[i
].name
);
888 g_free (info
->locals
);
889 g_free (info
->code_blocks
);