4 * Support for reading debug info from .mdb files.
7 * Mono Project (http://www.mono-project.com)
9 * Copyright (C) 2005-2008 Novell, Inc. (http://www.novell.com)
10 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
11 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
19 #ifdef HAVE_SYS_PARAM_H
20 #include <sys/param.h>
23 #include <mono/metadata/metadata.h>
24 #include <mono/metadata/tabledefs.h>
25 #include <mono/metadata/tokentype.h>
26 #include <mono/metadata/appdomain.h>
27 #include <mono/metadata/exception.h>
28 #include <mono/metadata/debug-helpers.h>
29 #include <mono/metadata/mono-debug.h>
30 #include <mono/metadata/debug-mono-symfile.h>
31 #include <mono/metadata/mono-endian.h>
32 #include <mono/metadata/metadata-internals.h>
33 #include <mono/metadata/class-internals.h>
34 #include <mono/utils/mono-mmap.h>
35 #include <mono/utils/bsearch.h>
44 #define RANGE_TABLE_CHUNK_SIZE 256
45 #define CLASS_TABLE_CHUNK_SIZE 256
46 #define TYPE_TABLE_PTR_CHUNK_SIZE 256
47 #define TYPE_TABLE_CHUNK_SIZE 65536
49 struct _MonoSymbolFile
{
50 const uint8_t *raw_contents
;
51 int raw_contents_size
;
52 void *raw_contents_handle
;
56 GHashTable
*method_hash
;
57 GHashTable
*source_hash
;
58 MonoSymbolFileOffsetTable
*offset_table
;
59 gboolean was_loaded_from_memory
;
63 free_method_info (MonoDebugMethodInfo
*minfo
)
69 free_source_info (MonoDebugSourceInfo
*sinfo
)
71 g_free (sinfo
->source_file
);
78 load_symfile (MonoDebugHandle
*handle
, MonoSymbolFile
*symfile
, mono_bool in_the_debugger
)
80 const char *ptr
, *start
;
85 ptr
= start
= (const char*)symfile
->raw_contents
;
90 ptr
+= sizeof(uint64_t);
91 if (magic
!= MONO_SYMBOL_FILE_MAGIC
) {
93 g_warning ("Symbol file %s is not a mono symbol file", symfile
->filename
);
98 ptr
+= sizeof(uint32_t);
100 ptr
+= sizeof(uint32_t);
103 * 50.0 is the frozen version for Mono 2.0.
105 * Nobody except me (Martin) is allowed to check the minor version.
107 if (major
!= MONO_SYMBOL_FILE_MAJOR_VERSION
) {
108 if (!in_the_debugger
)
109 g_warning ("Symbol file %s has incorrect version (expected %d.%d, got %d)",
110 symfile
->filename
, MONO_SYMBOL_FILE_MAJOR_VERSION
,
111 MONO_SYMBOL_FILE_MINOR_VERSION
, major
);
115 guid
= mono_guid_to_string ((const uint8_t *) ptr
);
118 if (strcmp (handle
->image
->guid
, guid
)) {
119 if (!in_the_debugger
)
120 g_warning ("Symbol file %s doesn't match image %s", symfile
->filename
,
121 handle
->image
->name
);
127 symfile
->major_version
= major
;
128 symfile
->minor_version
= minor
;
130 symfile
->offset_table
= (MonoSymbolFileOffsetTable
*) ptr
;
132 symfile
->method_hash
= g_hash_table_new_full (
133 NULL
, NULL
, NULL
, (GDestroyNotify
) free_method_info
);
135 symfile
->source_hash
= g_hash_table_new_full (
136 NULL
, NULL
, NULL
, (GDestroyNotify
) free_source_info
);
143 * mono_debug_open_mono_symbols:
146 mono_debug_open_mono_symbols (MonoDebugHandle
*handle
, const uint8_t *raw_contents
,
147 int size
, gboolean in_the_debugger
)
149 MonoSymbolFile
*symfile
;
151 mono_debugger_lock ();
152 symfile
= g_new0 (MonoSymbolFile
, 1);
154 if (raw_contents
!= NULL
) {
156 symfile
->raw_contents_size
= size
;
157 symfile
->raw_contents
= p
= (unsigned char *)g_malloc (size
);
158 memcpy (p
, raw_contents
, size
);
159 symfile
->filename
= g_strdup_printf ("LoadedFromMemory");
160 symfile
->was_loaded_from_memory
= TRUE
;
164 symfile
->filename
= g_strdup_printf ("%s.mdb", mono_image_get_filename (handle
->image
));
165 symfile
->was_loaded_from_memory
= FALSE
;
166 if ((f
= mono_file_map_open (symfile
->filename
))) {
167 symfile
->raw_contents_size
= mono_file_map_size (f
);
168 if (symfile
->raw_contents_size
== 0) {
169 if (!in_the_debugger
)
170 g_warning ("stat of %s failed: %s",
171 symfile
->filename
, g_strerror (errno
));
173 symfile
->raw_contents
= (const unsigned char *)mono_file_map (symfile
->raw_contents_size
, MONO_MMAP_READ
|MONO_MMAP_PRIVATE
, mono_file_map_fd (f
), 0, &symfile
->raw_contents_handle
);
176 mono_file_map_close (f
);
180 if (load_symfile (handle
, symfile
, in_the_debugger
)) {
181 mono_debugger_unlock ();
183 } else if (!in_the_debugger
) {
184 mono_debug_close_mono_symbol_file (symfile
);
185 mono_debugger_unlock ();
189 mono_debugger_unlock ();
194 * mono_debug_close_mono_symbol_file:
197 mono_debug_close_mono_symbol_file (MonoSymbolFile
*symfile
)
202 mono_debugger_lock ();
203 if (symfile
->method_hash
)
204 g_hash_table_destroy (symfile
->method_hash
);
206 if (symfile
->raw_contents
) {
207 if (symfile
->was_loaded_from_memory
)
208 g_free ((gpointer
)symfile
->raw_contents
);
210 mono_file_unmap ((gpointer
) symfile
->raw_contents
, symfile
->raw_contents_handle
);
213 g_free (symfile
->filename
);
215 mono_debugger_unlock ();
219 * mono_debug_symfile_is_loaded:
222 mono_debug_symfile_is_loaded (MonoSymbolFile
*symfile
)
224 return symfile
&& symfile
->offset_table
;
228 read_leb128 (const uint8_t *ptr
, const uint8_t **rptr
)
237 ret
= ret
| ((b
& 0x7f) << shift
);
239 } while ((b
& 0x80) == 0x80);
248 read_string (const uint8_t *ptr
, const uint8_t **endp
)
251 int len
= read_leb128 (ptr
, &ptr
);
253 s
= g_filename_from_utf8 ((const char *) ptr
, len
, NULL
, NULL
, NULL
);
261 MonoSymbolFile
*symfile
;
262 int line_base
, line_range
, max_address_incr
;
264 uint32_t last_line
, last_file
, last_offset
;
266 int line
, file
, offset
;
271 check_line (StatementMachine
*stm
, int offset
, MonoDebugSourceLocation
**location
)
273 gchar
*source_file
= NULL
;
275 if (stm
->offset
<= offset
) {
276 stm
->last_offset
= stm
->offset
;
277 stm
->last_file
= stm
->file
;
278 if (stm
->line
!= 0xfeefee)
279 stm
->last_line
= stm
->line
;
283 if (stm
->last_file
) {
284 int offset
= read32(&(stm
->symfile
->offset_table
->_source_table_offset
)) +
285 (stm
->last_file
- 1) * sizeof (MonoSymbolFileSourceEntry
);
286 MonoSymbolFileSourceEntry
*se
= (MonoSymbolFileSourceEntry
*)
287 (stm
->symfile
->raw_contents
+ offset
);
289 source_file
= read_string (stm
->symfile
->raw_contents
+ read32(&(se
->_data_offset
)), NULL
);
292 if (stm
->last_line
== 0) {
294 * The IL offset is less than the first IL offset which has a corresponding
301 *location
= g_new0 (MonoDebugSourceLocation
, 1);
302 (*location
)->source_file
= source_file
;
303 (*location
)->row
= stm
->last_line
;
304 (*location
)->il_offset
= stm
->last_offset
;
309 * mono_debug_symfile_lookup_location:
310 * \param minfo A \c MonoDebugMethodInfo which can be retrieved by \c mono_debug_lookup_method.
311 * \param offset IL offset within the corresponding method's CIL code.
313 * This function is similar to \c mono_debug_lookup_location, but we
314 * already looked up the method and also already did the
315 * native address -> IL offset mapping.
317 MonoDebugSourceLocation
*
318 mono_debug_symfile_lookup_location (MonoDebugMethodInfo
*minfo
, uint32_t offset
)
320 MonoDebugSourceLocation
*location
= NULL
;
321 MonoSymbolFile
*symfile
;
322 const unsigned char *ptr
;
323 StatementMachine stm
;
325 #define DW_LNS_copy 1
326 #define DW_LNS_advance_pc 2
327 #define DW_LNS_advance_line 3
328 #define DW_LNS_set_file 4
329 #define DW_LNS_const_add_pc 8
331 #define DW_LNE_end_sequence 1
332 #define DW_LNE_MONO_negate_is_hidden 0x40
334 #define DW_LNE_MONO__extensions_start 0x40
335 #define DW_LNE_MONO__extensions_end 0x7f
337 if ((symfile
= minfo
->handle
->symfile
) == NULL
)
340 stm
.line_base
= read32 (&symfile
->offset_table
->_line_number_table_line_base
);
341 stm
.line_range
= read32 (&symfile
->offset_table
->_line_number_table_line_range
);
342 stm
.opcode_base
= (uint8_t) read32 (&symfile
->offset_table
->_line_number_table_opcode_base
);
343 stm
.max_address_incr
= (255 - stm
.opcode_base
) / stm
.line_range
;
345 mono_debugger_lock ();
347 ptr
= symfile
->raw_contents
+ minfo
->lnt_offset
;
349 stm
.symfile
= symfile
;
350 stm
.offset
= stm
.last_offset
= 0;
356 stm
.is_hidden
= FALSE
;
359 uint8_t opcode
= *ptr
++;
362 uint8_t size
= *ptr
++;
363 const unsigned char *end_ptr
= ptr
+ size
;
367 if (opcode
== DW_LNE_end_sequence
) {
368 if (check_line (&stm
, -1, &location
))
371 } else if (opcode
== DW_LNE_MONO_negate_is_hidden
) {
372 stm
.is_hidden
= !stm
.is_hidden
;
373 } else if ((opcode
>= DW_LNE_MONO__extensions_start
) &&
374 (opcode
<= DW_LNE_MONO__extensions_end
)) {
375 ; // reserved for future extensions
377 g_warning ("Unknown extended opcode %x in LNT", opcode
);
382 } else if (opcode
< stm
.opcode_base
) {
385 if (check_line (&stm
, offset
, &location
))
388 case DW_LNS_advance_pc
:
389 stm
.offset
+= read_leb128 (ptr
, &ptr
);
391 case DW_LNS_advance_line
:
392 stm
.line
+= read_leb128 (ptr
, &ptr
);
394 case DW_LNS_set_file
:
395 stm
.file
= read_leb128 (ptr
, &ptr
);
397 case DW_LNS_const_add_pc
:
398 stm
.offset
+= stm
.max_address_incr
;
401 g_warning ("Unknown standard opcode %x in LNT", opcode
);
405 opcode
-= stm
.opcode_base
;
407 stm
.offset
+= opcode
/ stm
.line_range
;
408 stm
.line
+= stm
.line_base
+ (opcode
% stm
.line_range
);
410 if (check_line (&stm
, offset
, &location
))
416 mono_debugger_unlock ();
420 mono_debugger_unlock ();
425 add_line (StatementMachine
*stm
, GPtrArray
*il_offset_array
, GPtrArray
*line_number_array
, GPtrArray
*source_file_array
, GPtrArray
*hidden_array
)
427 g_ptr_array_add (il_offset_array
, GUINT_TO_POINTER (stm
->offset
));
428 g_ptr_array_add (line_number_array
, GUINT_TO_POINTER (stm
->line
));
429 g_ptr_array_add (source_file_array
, GUINT_TO_POINTER (stm
->file
));
430 g_ptr_array_add (hidden_array
, GUINT_TO_POINTER (stm
->is_hidden
|| stm
->line
<= 0));
432 if (!stm
->is_hidden
&& !stm
->first_file
)
433 stm
->first_file
= stm
->file
;
437 * mono_debug_symfile_free_location:
439 * Free a \c MonoDebugSourceLocation returned by
440 * \c mono_debug_symfile_lookup_location
443 mono_debug_symfile_free_location (MonoDebugSourceLocation
*location
)
445 g_free (location
->source_file
);
450 * LOCKING: Assumes the debugger lock is held.
452 static MonoDebugSourceInfo
*
453 get_source_info (MonoSymbolFile
*symfile
, int index
)
455 MonoDebugSourceInfo
*info
;
457 info
= (MonoDebugSourceInfo
*)g_hash_table_lookup (symfile
->source_hash
, GUINT_TO_POINTER (index
));
459 int offset
= read32(&(symfile
->offset_table
->_source_table_offset
)) +
460 (index
- 1) * sizeof (MonoSymbolFileSourceEntry
);
461 MonoSymbolFileSourceEntry
*se
= (MonoSymbolFileSourceEntry
*)
462 (symfile
->raw_contents
+ offset
);
463 const uint8_t *ptr
= symfile
->raw_contents
+ read32(&(se
->_data_offset
));
465 info
= g_new0 (MonoDebugSourceInfo
, 1);
466 info
->source_file
= read_string (ptr
, &ptr
);
467 info
->guid
= (guint8
*)g_malloc0 (16);
468 memcpy (info
->guid
, ptr
, 16);
470 info
->hash
= (guint8
*)g_malloc0 (16);
471 memcpy (info
->hash
, ptr
, 16);
473 g_hash_table_insert (symfile
->source_hash
, GUINT_TO_POINTER (index
), info
);
479 LNT_FLAG_HAS_COLUMN_INFO
= 1 << 1,
480 LNT_FLAG_HAS_END_INFO
= 1 << 2,
481 } LineNumberTableFlags
;
483 static LineNumberTableFlags
484 method_get_lnt_flags (MonoDebugMethodInfo
*minfo
)
486 MonoSymbolFile
*symfile
;
487 const unsigned char *ptr
;
490 if ((symfile
= minfo
->handle
->symfile
) == NULL
)
491 return (LineNumberTableFlags
)0;
493 ptr
= symfile
->raw_contents
+ minfo
->data_offset
;
495 /* Has to read 'flags' which is preceeded by a bunch of other data */
496 /* compile_unit_index */
497 read_leb128 (ptr
, &ptr
);
498 /* local variable table offset */
499 read_leb128 (ptr
, &ptr
);
501 read_leb128 (ptr
, &ptr
);
502 /* code block table offset */
503 read_leb128 (ptr
, &ptr
);
504 /* scope variable table offset */
505 read_leb128 (ptr
, &ptr
);
506 /* real name offset */
507 read_leb128 (ptr
, &ptr
);
509 flags
= read_leb128 (ptr
, &ptr
);
510 return (LineNumberTableFlags
)flags
;
514 * mono_debug_symfile_get_seq_points:
516 * On return, SOURCE_FILE_LIST will point to a GPtrArray of MonoDebugSourceFile
517 * structures, and SOURCE_FILES will contain indexes into this array.
518 * The MonoDebugSourceFile structures are owned by this module.
521 mono_debug_symfile_get_seq_points (MonoDebugMethodInfo
*minfo
, char **source_file
, GPtrArray
**source_file_list
, int **source_files
, MonoSymSeqPoint
**seq_points
, int *n_seq_points
)
523 // FIXME: Unify this with mono_debug_symfile_lookup_location
524 MonoSymbolFile
*symfile
;
525 const unsigned char *ptr
;
526 StatementMachine stm
;
528 LineNumberTableFlags flags
;
529 GPtrArray
*il_offset_array
, *line_number_array
, *source_file_array
, *hidden_array
;
530 gboolean has_column_info
, has_end_info
;
531 MonoSymSeqPoint
*sps
;
533 if (source_file_list
)
534 *source_file_list
= NULL
;
540 *source_files
= NULL
;
544 if ((symfile
= minfo
->handle
->symfile
) == NULL
)
547 flags
= method_get_lnt_flags (minfo
);
548 has_column_info
= (flags
& LNT_FLAG_HAS_COLUMN_INFO
) > 0;
549 has_end_info
= (flags
& LNT_FLAG_HAS_END_INFO
) > 0;
551 il_offset_array
= g_ptr_array_new ();
552 line_number_array
= g_ptr_array_new ();
553 source_file_array
= g_ptr_array_new ();
554 hidden_array
= g_ptr_array_new();
556 stm
.line_base
= read32 (&symfile
->offset_table
->_line_number_table_line_base
);
557 stm
.line_range
= read32 (&symfile
->offset_table
->_line_number_table_line_range
);
558 stm
.opcode_base
= (uint8_t) read32 (&symfile
->offset_table
->_line_number_table_opcode_base
);
559 stm
.max_address_incr
= (255 - stm
.opcode_base
) / stm
.line_range
;
561 mono_debugger_lock ();
563 ptr
= symfile
->raw_contents
+ minfo
->lnt_offset
;
565 stm
.symfile
= symfile
;
566 stm
.offset
= stm
.last_offset
= 0;
572 stm
.is_hidden
= FALSE
;
575 uint8_t opcode
= *ptr
++;
578 uint8_t size
= *ptr
++;
579 const unsigned char *end_ptr
= ptr
+ size
;
583 if (opcode
== DW_LNE_end_sequence
) {
584 if (il_offset_array
->len
== 0)
588 } else if (opcode
== DW_LNE_MONO_negate_is_hidden
) {
589 stm
.is_hidden
= !stm
.is_hidden
;
590 } else if ((opcode
>= DW_LNE_MONO__extensions_start
) &&
591 (opcode
<= DW_LNE_MONO__extensions_end
)) {
592 ; // reserved for future extensions
594 g_warning ("Unknown extended opcode %x in LNT", opcode
);
599 } else if (opcode
< stm
.opcode_base
) {
602 add_line (&stm
, il_offset_array
, line_number_array
, source_file_array
, hidden_array
);
604 case DW_LNS_advance_pc
:
605 stm
.offset
+= read_leb128 (ptr
, &ptr
);
607 case DW_LNS_advance_line
:
608 stm
.line
+= read_leb128 (ptr
, &ptr
);
610 case DW_LNS_set_file
:
611 stm
.file
= read_leb128 (ptr
, &ptr
);
613 case DW_LNS_const_add_pc
:
614 stm
.offset
+= stm
.max_address_incr
;
617 g_warning ("Unknown standard opcode %x in LNT", opcode
);
618 g_assert_not_reached ();
621 opcode
-= stm
.opcode_base
;
623 stm
.offset
+= opcode
/ stm
.line_range
;
624 stm
.line
+= stm
.line_base
+ (opcode
% stm
.line_range
);
626 add_line (&stm
, il_offset_array
, line_number_array
, source_file_array
, hidden_array
);
630 if (!stm
.file
&& stm
.first_file
)
631 stm
.file
= stm
.first_file
;
633 if (stm
.file
&& source_file
) {
634 int offset
= read32(&(stm
.symfile
->offset_table
->_source_table_offset
)) +
635 (stm
.file
- 1) * sizeof (MonoSymbolFileSourceEntry
);
636 MonoSymbolFileSourceEntry
*se
= (MonoSymbolFileSourceEntry
*)
637 (stm
.symfile
->raw_contents
+ offset
);
640 *source_file
= read_string (stm
.symfile
->raw_contents
+ read32(&(se
->_data_offset
)), NULL
);
643 if (source_file_list
) {
644 int file
, last_file
= 0;
646 *source_file_list
= g_ptr_array_new ();
648 *source_files
= (int *)g_malloc (il_offset_array
->len
* sizeof (int));
650 for (i
= 0; i
< il_offset_array
->len
; ++i
) {
651 file
= GPOINTER_TO_UINT (g_ptr_array_index (source_file_array
, i
));
652 if (file
&& file
!= last_file
) {
653 MonoDebugSourceInfo
*info
= get_source_info (symfile
, file
);
655 g_ptr_array_add (*source_file_list
, info
);
659 (*source_files
) [i
] = (*source_file_list
)->len
- 1;
664 g_assert (seq_points
);
666 n
= 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
))) {
674 *seq_points
= sps
= g_new0 (MonoSymSeqPoint
, n
);
676 for (i
= 0; i
< il_offset_array
->len
; ++i
) {
677 MonoSymSeqPoint
*sp
= &(sps
[j
]);
678 if (!GPOINTER_TO_UINT (g_ptr_array_index (hidden_array
, i
))) {
679 sp
->il_offset
= GPOINTER_TO_UINT (g_ptr_array_index (il_offset_array
, i
));
680 sp
->line
= GPOINTER_TO_UINT (g_ptr_array_index (line_number_array
, i
));
688 if (has_column_info
) {
690 for (i
= 0; i
< il_offset_array
->len
; ++i
) {
691 MonoSymSeqPoint
*sp
= &(sps
[j
]);
692 int column
= read_leb128 (ptr
, &ptr
);
693 if (!GPOINTER_TO_UINT (g_ptr_array_index (hidden_array
, i
))) {
702 for (i
= 0; i
< il_offset_array
->len
; ++i
) {
703 MonoSymSeqPoint
*sp
= &(sps
[j
]);
704 int end_row
, end_column
= -1;
706 end_row
= read_leb128 (ptr
, &ptr
);
707 if (end_row
!= 0xffffff) {
708 end_row
+= GPOINTER_TO_UINT (g_ptr_array_index (line_number_array
, i
));
709 end_column
= read_leb128 (ptr
, &ptr
);
710 if (!GPOINTER_TO_UINT (g_ptr_array_index (hidden_array
, i
))) {
711 sp
->end_line
= end_row
;
712 sp
->end_column
= end_column
;
720 g_ptr_array_free (il_offset_array
, TRUE
);
721 g_ptr_array_free (line_number_array
, TRUE
);
722 g_ptr_array_free (hidden_array
, TRUE
);
724 mono_debugger_unlock ();
729 compare_method (const void *key
, const void *object
)
731 uint32_t token
= GPOINTER_TO_UINT (key
);
732 MonoSymbolFileMethodEntry
*me
= (MonoSymbolFileMethodEntry
*)object
;
734 return token
- read32(&(me
->_token
));
738 * mono_debug_symfile_lookup_method:
740 MonoDebugMethodInfo
*
741 mono_debug_symfile_lookup_method (MonoDebugHandle
*handle
, MonoMethod
*method
)
743 MonoSymbolFileMethodEntry
*first_ie
, *ie
;
744 MonoDebugMethodInfo
*minfo
;
745 MonoSymbolFile
*symfile
= handle
->symfile
;
747 if (!symfile
->method_hash
)
750 if (handle
->image
!= mono_class_get_image (mono_method_get_class (method
)))
753 mono_debugger_lock ();
755 minfo
= (MonoDebugMethodInfo
*)g_hash_table_lookup (symfile
->method_hash
, method
);
757 mono_debugger_unlock ();
761 first_ie
= (MonoSymbolFileMethodEntry
*)
762 (symfile
->raw_contents
+ read32(&(symfile
->offset_table
->_method_table_offset
)));
764 ie
= (MonoSymbolFileMethodEntry
*)mono_binary_search (GUINT_TO_POINTER (mono_method_get_token (method
)), first_ie
,
765 read32(&(symfile
->offset_table
->_method_count
)),
766 sizeof (MonoSymbolFileMethodEntry
), compare_method
);
769 mono_debugger_unlock ();
773 minfo
= g_new0 (MonoDebugMethodInfo
, 1);
774 minfo
->index
= (ie
- first_ie
) + 1;
775 minfo
->method
= method
;
776 minfo
->handle
= handle
;
778 minfo
->data_offset
= read32 (&(ie
->_data_offset
));
779 minfo
->lnt_offset
= read32 (&(ie
->_line_number_table
));
781 g_hash_table_insert (symfile
->method_hash
, method
, minfo
);
783 mono_debugger_unlock ();
788 * mono_debug_symfile_lookup_locals:
790 * Return information about the local variables of \p minfo from the symbol file.
791 * Return NULL if no information can be found.
792 * The result should be freed using \c mono_debug_symfile_free_locals.
795 mono_debug_symfile_lookup_locals (MonoDebugMethodInfo
*minfo
)
797 MonoSymbolFile
*symfile
= minfo
->handle
->symfile
;
799 int i
, len
, locals_offset
, num_locals
, block_index
;
800 int code_block_table_offset
;
801 MonoDebugLocalsInfo
*res
;
806 p
= symfile
->raw_contents
+ minfo
->data_offset
;
808 /* compile_unit_index = */ read_leb128 (p
, &p
);
809 locals_offset
= read_leb128 (p
, &p
);
810 /* namespace_id = */ read_leb128 (p
, &p
);
811 code_block_table_offset
= read_leb128 (p
, &p
);
813 res
= g_new0 (MonoDebugLocalsInfo
, 1);
815 p
= symfile
->raw_contents
+ code_block_table_offset
;
816 res
->num_blocks
= read_leb128 (p
, &p
);
817 res
->code_blocks
= g_new0 (MonoDebugCodeBlock
, res
->num_blocks
);
818 for (i
= 0; i
< res
->num_blocks
; ++i
) {
819 res
->code_blocks
[i
].type
= read_leb128 (p
, &p
);
820 res
->code_blocks
[i
].parent
= read_leb128 (p
, &p
);
821 res
->code_blocks
[i
].start_offset
= read_leb128 (p
, &p
);
822 res
->code_blocks
[i
].end_offset
= read_leb128 (p
, &p
);
825 p
= symfile
->raw_contents
+ locals_offset
;
826 num_locals
= read_leb128 (p
, &p
);
828 res
->num_locals
= num_locals
;
829 res
->locals
= g_new0 (MonoDebugLocalVar
, num_locals
);
831 for (i
= 0; i
< num_locals
; ++i
) {
832 res
->locals
[i
].index
= read_leb128 (p
, &p
);
833 len
= read_leb128 (p
, &p
);
834 res
->locals
[i
].name
= (char *)g_malloc (len
+ 1);
835 memcpy (res
->locals
[i
].name
, p
, len
);
836 res
->locals
[i
].name
[len
] = '\0';
838 block_index
= read_leb128 (p
, &p
);
839 if (block_index
>= 1 && block_index
<= res
->num_blocks
)
840 res
->locals
[i
].block
= &res
->code_blocks
[block_index
- 1];
846 #else /* DISABLE_MDB */
849 mono_debug_open_mono_symbols (MonoDebugHandle
*handle
, const uint8_t *raw_contents
,
850 int size
, gboolean in_the_debugger
)
856 mono_debug_close_mono_symbol_file (MonoSymbolFile
*symfile
)
861 mono_debug_symfile_is_loaded (MonoSymbolFile
*symfile
)
866 MonoDebugMethodInfo
*
867 mono_debug_symfile_lookup_method (MonoDebugHandle
*handle
, MonoMethod
*method
)
873 mono_debug_symfile_get_seq_points (MonoDebugMethodInfo
*minfo
, char **source_file
, GPtrArray
**source_file_list
, int **source_files
, MonoSymSeqPoint
**seq_points
, int *n_seq_points
)
875 g_assert_not_reached ();
878 MonoDebugSourceLocation
*
879 mono_debug_symfile_lookup_location (MonoDebugMethodInfo
*minfo
, uint32_t offset
)
885 mono_debug_symfile_lookup_locals (MonoDebugMethodInfo
*minfo
)
891 mono_debug_symfile_free_location (MonoDebugSourceLocation
*location
)