2 * debug-mini.c: Mini-specific debugging stuff.
5 * Martin Baulig (martin@ximian.com)
7 * (C) 2003 Ximian, Inc.
13 #include <mono/metadata/verify.h>
14 #include <mono/metadata/mono-config.h>
15 #include <mono/metadata/mono-debug.h>
16 #include <mono/metadata/appdomain.h>
17 #include <mono/metadata/threads-types.h>
19 #define _IN_THE_MONO_DEBUGGER
20 #include <mono/metadata/mono-debug-debugger.h>
22 #include <mono/utils/valgrind.h>
27 } MiniDebugBreakpointInfo
;
31 MonoDebugMethodJitInfo
*jit
;
33 guint32 has_line_numbers
;
34 guint32 breakpoint_id
;
35 } MiniDebugMethodInfo
;
38 record_line_number (MiniDebugMethodInfo
*info
, guint32 address
, guint32 offset
)
40 MonoDebugLineNumberEntry lne
;
42 lne
.native_offset
= address
;
43 lne
.il_offset
= offset
;
45 g_array_append_val (info
->line_numbers
, lne
);
50 mono_debug_init_method (MonoCompile
*cfg
, MonoBasicBlock
*start_block
, guint32 breakpoint_id
)
52 MiniDebugMethodInfo
*info
;
54 if (!mono_debug_enabled ())
57 info
= g_new0 (MiniDebugMethodInfo
, 1);
58 info
->breakpoint_id
= breakpoint_id
;
60 cfg
->debug_info
= info
;
64 mono_debug_open_method (MonoCompile
*cfg
)
66 MiniDebugMethodInfo
*info
;
67 MonoDebugMethodJitInfo
*jit
;
68 MonoMethodHeader
*header
;
70 info
= (MiniDebugMethodInfo
*) cfg
->debug_info
;
74 mono_class_init (cfg
->method
->klass
);
79 info
->jit
= jit
= g_new0 (MonoDebugMethodJitInfo
, 1);
80 info
->line_numbers
= g_array_new (FALSE
, TRUE
, sizeof (MonoDebugLineNumberEntry
));
81 jit
->num_locals
= header
->num_locals
;
82 jit
->locals
= g_new0 (MonoDebugVarInfo
, jit
->num_locals
);
86 write_variable (MonoInst
*inst
, MonoDebugVarInfo
*var
)
88 var
->type
= inst
->inst_vtype
;
90 if (inst
->opcode
== OP_REGVAR
)
91 var
->index
= inst
->dreg
| MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER
;
92 else if (inst
->flags
& MONO_INST_IS_DEAD
)
93 var
->index
= MONO_DEBUG_VAR_ADDRESS_MODE_DEAD
;
94 else if (inst
->opcode
== OP_REGOFFSET
) {
95 /* the debug interface needs fixing to allow 0(%base) address */
96 var
->index
= inst
->inst_basereg
| MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET
;
97 var
->offset
= inst
->inst_offset
;
98 } else if (inst
->opcode
== OP_GSHAREDVT_ARG_REGOFFSET
) {
99 var
->index
= inst
->inst_basereg
| MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET_INDIR
;
100 var
->offset
= inst
->inst_offset
;
101 } else if (inst
->opcode
== OP_GSHAREDVT_LOCAL
) {
102 var
->index
= inst
->inst_imm
| MONO_DEBUG_VAR_ADDRESS_MODE_GSHAREDVT_LOCAL
;
103 } else if (inst
->opcode
== OP_VTARG_ADDR
) {
106 vtaddr
= inst
->inst_left
;
107 g_assert (vtaddr
->opcode
== OP_REGOFFSET
);
108 var
->offset
= vtaddr
->inst_offset
;
109 var
->index
= vtaddr
->inst_basereg
| MONO_DEBUG_VAR_ADDRESS_MODE_VTADDR
;
111 g_assert_not_reached ();
116 * mono_debug_add_vg_method:
118 * Register symbol information for the method with valgrind
121 mono_debug_add_vg_method (MonoMethod
*method
, MonoDebugMethodJitInfo
*jit
)
123 #ifdef VALGRIND_ADD_LINE_INFO
124 MonoMethodHeader
*header
;
125 MonoDebugMethodInfo
*minfo
;
127 char *filename
= NULL
;
128 guint32 address
, line_number
;
129 const char *full_name
;
133 if (!RUNNING_ON_VALGRIND
)
136 header
= mono_method_get_header (method
);
138 full_name
= mono_method_full_name (method
, TRUE
);
140 addresses
= g_new0 (guint32
, header
->code_size
+ 1);
141 lines
= g_new0 (guint32
, header
->code_size
+ 1);
144 * Very simple code to convert the addr->offset mappings that mono has
145 * into [addr-addr] ->line number mappings.
148 minfo
= mono_debug_lookup_method (method
);
150 /* Create offset->line number mapping */
151 for (i
= 0; i
< header
->code_size
; ++i
) {
152 MonoDebugSourceLocation
*location
;
154 location
= mono_debug_symfile_lookup_location (minfo
, i
);
158 lines
[i
] = location
.row
;
160 filename
= location
.source_file
;
162 mono_debug_free_source_location (location
);
166 /* Create address->offset mapping */
167 for (i
= 0; i
< jit
->num_line_numbers
; ++i
) {
168 MonoDebugLineNumberEntry
*lne
= jit
->line_numbers
[i
];
170 g_assert (lne
->offset
<= header
->code_size
);
172 if ((addresses
[lne
->offset
] == 0) || (lne
->address
< addresses
[lne
->offset
]))
173 addresses
[lne
->offset
] = lne
->address
;
175 /* Fill out missing addresses */
177 for (i
= 0; i
< header
->code_size
; ++i
) {
178 if (addresses
[i
] == 0)
179 addresses
[i
] = address
;
181 address
= addresses
[i
];
187 while (i
< header
->code_size
) {
188 if (lines
[i
] == line_number
)
191 if (line_number
> 0) {
192 //g_assert (addresses [i] - 1 >= address);
194 if (addresses
[i
] - 1 >= address
) {
195 VALGRIND_ADD_LINE_INFO (jit
->code_start
+ address
, jit
->code_start
+ addresses
[i
] - 1, filename
, line_number
);
196 //printf ("[%d-%d] -> %d.\n", address, addresses [i] - 1, line_number);
199 address
= addresses
[i
];
200 line_number
= lines
[i
];
204 if (line_number
> 0) {
205 VALGRIND_ADD_LINE_INFO (jit
->code_start
+ address
, jit
->code_start
+ jit
->code_size
- 1, filename
, line_number
);
206 //printf ("[%d-%d] -> %d.\n", address, jit->code_size - 1, line_number);
209 VALGRIND_ADD_SYMBOL (jit
->code_start
, jit
->code_size
, full_name
);
213 mono_metadata_free_mh (header
);
214 #endif /* VALGRIND_ADD_LINE_INFO */
218 mono_debug_close_method (MonoCompile
*cfg
)
220 MiniDebugMethodInfo
*info
;
221 MonoDebugMethodJitInfo
*jit
;
222 MonoMethodHeader
*header
;
223 MonoMethodSignature
*sig
;
224 MonoDebugMethodAddress
*debug_info
;
228 info
= (MiniDebugMethodInfo
*) cfg
->debug_info
;
229 if (!info
|| !info
->jit
) {
235 method
= cfg
->method
;
236 header
= cfg
->header
;
237 sig
= mono_method_signature (method
);
240 jit
->code_start
= cfg
->native_code
;
241 jit
->epilogue_begin
= cfg
->epilog_begin
;
242 jit
->code_size
= cfg
->code_len
;
244 if (jit
->epilogue_begin
)
245 record_line_number (info
, jit
->epilogue_begin
, header
->code_size
);
247 jit
->num_params
= sig
->param_count
;
248 jit
->params
= g_new0 (MonoDebugVarInfo
, jit
->num_params
);
250 for (i
= 0; i
< jit
->num_locals
; i
++)
251 write_variable (cfg
->locals
[i
], &jit
->locals
[i
]);
254 jit
->this_var
= g_new0 (MonoDebugVarInfo
, 1);
255 write_variable (cfg
->args
[0], jit
->this_var
);
258 for (i
= 0; i
< jit
->num_params
; i
++)
259 write_variable (cfg
->args
[i
+ sig
->hasthis
], &jit
->params
[i
]);
261 if (cfg
->gsharedvt_info_var
) {
262 jit
->gsharedvt_info_var
= g_new0 (MonoDebugVarInfo
, 1);
263 jit
->gsharedvt_locals_var
= g_new0 (MonoDebugVarInfo
, 1);
264 write_variable (cfg
->gsharedvt_info_var
, jit
->gsharedvt_info_var
);
265 write_variable (cfg
->gsharedvt_locals_var
, jit
->gsharedvt_locals_var
);
268 jit
->num_line_numbers
= info
->line_numbers
->len
;
269 jit
->line_numbers
= g_new0 (MonoDebugLineNumberEntry
, jit
->num_line_numbers
);
271 for (i
= 0; i
< jit
->num_line_numbers
; i
++)
272 jit
->line_numbers
[i
] = g_array_index (info
->line_numbers
, MonoDebugLineNumberEntry
, i
);
274 debug_info
= mono_debug_add_method (cfg
->method_to_register
, jit
, cfg
->domain
);
276 mono_debug_add_vg_method (method
, jit
);
278 mono_debug_free_method_jit_info (jit
);
279 mono_debug_free_method (cfg
);
283 mono_debug_free_method (MonoCompile
*cfg
)
285 MiniDebugMethodInfo
*info
;
287 info
= (MiniDebugMethodInfo
*) cfg
->debug_info
;
289 if (info
->line_numbers
)
290 g_array_free (info
->line_numbers
, TRUE
);
292 cfg
->debug_info
= NULL
;
297 mono_debug_record_line_number (MonoCompile
*cfg
, MonoInst
*ins
, guint32 address
)
299 MiniDebugMethodInfo
*info
;
300 MonoMethodHeader
*header
;
303 info
= (MiniDebugMethodInfo
*) cfg
->debug_info
;
304 if (!info
|| !info
->jit
|| !ins
->cil_code
)
307 header
= cfg
->header
;
310 if ((ins
->cil_code
< header
->code
) ||
311 (ins
->cil_code
> header
->code
+ header
->code_size
))
314 offset
= ins
->cil_code
- header
->code
;
315 if (!info
->has_line_numbers
) {
316 info
->jit
->prologue_end
= address
;
317 info
->has_line_numbers
= TRUE
;
320 record_line_number (info
, address
, offset
);
324 mono_debug_open_block (MonoCompile
*cfg
, MonoBasicBlock
*bb
, guint32 address
)
326 MiniDebugMethodInfo
*info
;
327 MonoMethodHeader
*header
;
330 info
= (MiniDebugMethodInfo
*) cfg
->debug_info
;
331 if (!info
|| !info
->jit
|| !bb
->cil_code
)
334 header
= cfg
->header
;
337 if ((bb
->cil_code
< header
->code
) ||
338 (bb
->cil_code
> header
->code
+ header
->code_size
))
341 offset
= bb
->cil_code
- header
->code
;
342 if (!info
->has_line_numbers
) {
343 info
->jit
->prologue_end
= address
;
344 info
->has_line_numbers
= TRUE
;
347 record_line_number (info
, address
, offset
);
351 encode_value (gint32 value
, guint8
*buf
, guint8
**endbuf
)
355 //printf ("ENCODE: %d 0x%x.\n", value, value);
358 * Same encoding as the one used in the metadata, extended to handle values
359 * greater than 0x1fffffff.
361 if ((value
>= 0) && (value
<= 127))
363 else if ((value
>= 0) && (value
<= 16383)) {
364 p
[0] = 0x80 | (value
>> 8);
365 p
[1] = value
& 0xff;
367 } else if ((value
>= 0) && (value
<= 0x1fffffff)) {
368 p
[0] = (value
>> 24) | 0xc0;
369 p
[1] = (value
>> 16) & 0xff;
370 p
[2] = (value
>> 8) & 0xff;
371 p
[3] = value
& 0xff;
376 p
[1] = (value
>> 24) & 0xff;
377 p
[2] = (value
>> 16) & 0xff;
378 p
[3] = (value
>> 8) & 0xff;
379 p
[4] = value
& 0xff;
387 decode_value (guint8
*ptr
, guint8
**rptr
)
392 if ((b
& 0x80) == 0){
395 } else if ((b
& 0x40) == 0){
396 len
= ((b
& 0x3f) << 8 | ptr
[1]);
398 } else if (b
!= 0xff) {
399 len
= ((b
& 0x1f) << 24) |
406 len
= (ptr
[1] << 24) | (ptr
[2] << 16) | (ptr
[3] << 8) | ptr
[4];
412 //printf ("DECODE: %d.\n", len);
417 serialize_variable (MonoDebugVarInfo
*var
, guint8
*p
, guint8
**endbuf
)
419 guint32 flags
= var
->index
& MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS
;
421 encode_value (var
->index
, p
, &p
);
424 case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER
:
426 case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET
:
427 case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET_INDIR
:
428 case MONO_DEBUG_VAR_ADDRESS_MODE_VTADDR
:
429 encode_value (var
->offset
, p
, &p
);
431 case MONO_DEBUG_VAR_ADDRESS_MODE_GSHAREDVT_LOCAL
:
432 case MONO_DEBUG_VAR_ADDRESS_MODE_DEAD
:
435 g_assert_not_reached ();
441 mono_debug_serialize_debug_info (MonoCompile
*cfg
, guint8
**out_buf
, guint32
*buf_len
)
443 MonoDebugMethodJitInfo
*jit
;
444 guint32 size
, prev_offset
, prev_native_offset
;
448 /* Can't use cfg->debug_info as it is freed by close_method () */
449 jit
= mono_debug_find_method (cfg
->method
, mono_domain_get ());
455 size
= ((jit
->num_params
+ jit
->num_locals
+ 1) * 10) + (jit
->num_line_numbers
* 10) + 64;
456 p
= buf
= g_malloc (size
);
457 encode_value (jit
->epilogue_begin
, p
, &p
);
458 encode_value (jit
->prologue_end
, p
, &p
);
459 encode_value (jit
->code_size
, p
, &p
);
461 for (i
= 0; i
< jit
->num_params
; ++i
)
462 serialize_variable (&jit
->params
[i
], p
, &p
);
464 if (mono_method_signature (cfg
->method
)->hasthis
)
465 serialize_variable (jit
->this_var
, p
, &p
);
467 for (i
= 0; i
< jit
->num_locals
; i
++)
468 serialize_variable (&jit
->locals
[i
], p
, &p
);
470 if (jit
->gsharedvt_info_var
) {
471 encode_value (1, p
, &p
);
472 serialize_variable (jit
->gsharedvt_info_var
, p
, &p
);
473 serialize_variable (jit
->gsharedvt_locals_var
, p
, &p
);
475 encode_value (0, p
, &p
);
478 encode_value (jit
->num_line_numbers
, p
, &p
);
481 prev_native_offset
= 0;
482 for (i
= 0; i
< jit
->num_line_numbers
; ++i
) {
483 /* Sometimes, the offset values are not in increasing order */
484 MonoDebugLineNumberEntry
*lne
= &jit
->line_numbers
[i
];
485 encode_value (lne
->il_offset
- prev_offset
, p
, &p
);
486 encode_value (lne
->native_offset
- prev_native_offset
, p
, &p
);
487 prev_offset
= lne
->il_offset
;
488 prev_native_offset
= lne
->native_offset
;
491 g_assert (p
- buf
< size
);
498 deserialize_variable (MonoDebugVarInfo
*var
, guint8
*p
, guint8
**endbuf
)
502 var
->index
= decode_value (p
, &p
);
504 flags
= var
->index
& MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS
;
507 case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER
:
509 case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET
:
510 case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET_INDIR
:
511 case MONO_DEBUG_VAR_ADDRESS_MODE_VTADDR
:
512 var
->offset
= decode_value (p
, &p
);
514 case MONO_DEBUG_VAR_ADDRESS_MODE_GSHAREDVT_LOCAL
:
515 case MONO_DEBUG_VAR_ADDRESS_MODE_DEAD
:
518 g_assert_not_reached ();
523 static MonoDebugMethodJitInfo
*
524 deserialize_debug_info (MonoMethod
*method
, guint8
*code_start
, guint8
*buf
, guint32 buf_len
)
526 MonoMethodHeader
*header
;
527 gint32 offset
, native_offset
, prev_offset
, prev_native_offset
;
528 MonoDebugMethodJitInfo
*jit
;
532 header
= mono_method_get_header (method
);
535 jit
= g_new0 (MonoDebugMethodJitInfo
, 1);
536 jit
->code_start
= code_start
;
537 jit
->num_locals
= header
->num_locals
;
538 jit
->locals
= g_new0 (MonoDebugVarInfo
, jit
->num_locals
);
539 jit
->num_params
= mono_method_signature (method
)->param_count
;
540 jit
->params
= g_new0 (MonoDebugVarInfo
, jit
->num_params
);
543 jit
->epilogue_begin
= decode_value (p
, &p
);
544 jit
->prologue_end
= decode_value (p
, &p
);
545 jit
->code_size
= decode_value (p
, &p
);
547 for (i
= 0; i
< jit
->num_params
; ++i
)
548 deserialize_variable (&jit
->params
[i
], p
, &p
);
550 if (mono_method_signature (method
)->hasthis
) {
551 jit
->this_var
= g_new0 (MonoDebugVarInfo
, 1);
552 deserialize_variable (jit
->this_var
, p
, &p
);
555 for (i
= 0; i
< jit
->num_locals
; i
++)
556 deserialize_variable (&jit
->locals
[i
], p
, &p
);
558 if (decode_value (p
, &p
)) {
559 jit
->gsharedvt_info_var
= g_new0 (MonoDebugVarInfo
, 1);
560 jit
->gsharedvt_locals_var
= g_new0 (MonoDebugVarInfo
, 1);
561 deserialize_variable (jit
->gsharedvt_info_var
, p
, &p
);
562 deserialize_variable (jit
->gsharedvt_locals_var
, p
, &p
);
565 jit
->num_line_numbers
= decode_value (p
, &p
);
566 jit
->line_numbers
= g_new0 (MonoDebugLineNumberEntry
, jit
->num_line_numbers
);
569 prev_native_offset
= 0;
570 for (i
= 0; i
< jit
->num_line_numbers
; ++i
) {
571 MonoDebugLineNumberEntry
*lne
= &jit
->line_numbers
[i
];
573 offset
= prev_offset
+ decode_value (p
, &p
);
574 native_offset
= prev_native_offset
+ decode_value (p
, &p
);
576 lne
->native_offset
= native_offset
;
577 lne
->il_offset
= offset
;
579 prev_offset
= offset
;
580 prev_native_offset
= native_offset
;
583 mono_metadata_free_mh (header
);
588 mono_debug_add_aot_method (MonoDomain
*domain
, MonoMethod
*method
, guint8
*code_start
,
589 guint8
*debug_info
, guint32 debug_info_len
)
591 MonoDebugMethodJitInfo
*jit
;
593 if (!mono_debug_enabled ())
596 if ((method
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) ||
597 (method
->iflags
& METHOD_IMPL_ATTRIBUTE_RUNTIME
) ||
598 (method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) ||
599 (method
->flags
& METHOD_ATTRIBUTE_ABSTRACT
) ||
600 (method
->wrapper_type
!= MONO_WRAPPER_NONE
))
603 if (debug_info_len
== 0)
606 jit
= deserialize_debug_info (method
, code_start
, debug_info
, debug_info_len
);
608 mono_debug_add_method (method
, jit
, domain
);
610 mono_debug_add_vg_method (method
, jit
);
612 mono_debug_free_method_jit_info (jit
);
616 print_var_info (MonoDebugVarInfo
*info
, int idx
, const char *name
, const char *type
)
618 switch (info
->index
& MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS
) {
619 case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER
:
620 g_print ("%s %s (%d) in register %s\n", type
, name
, idx
, mono_arch_regname (info
->index
& (~MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS
)));
622 case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET
:
623 g_print ("%s %s (%d) in memory: base register %s + %d\n", type
, name
, idx
, mono_arch_regname (info
->index
& (~MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS
)), info
->offset
);
625 case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET_INDIR
:
626 g_print ("%s %s (%d) in indir memory: base register %s + %d\n", type
, name
, idx
, mono_arch_regname (info
->index
& (~MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS
)), info
->offset
);
628 case MONO_DEBUG_VAR_ADDRESS_MODE_GSHAREDVT_LOCAL
:
629 g_print ("%s %s (%d) gsharedvt local.\n", type
, name
, idx
);
631 case MONO_DEBUG_VAR_ADDRESS_MODE_VTADDR
:
632 g_print ("%s %s (%d) vt address: base register %s + %d\n", type
, name
, idx
, mono_arch_regname (info
->index
& (~MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS
)), info
->offset
);
634 case MONO_DEBUG_VAR_ADDRESS_MODE_TWO_REGISTERS
:
636 g_assert_not_reached ();
641 * mono_debug_print_locals:
643 * Prints to stdout the information about the local variables in
644 * a method (if @only_arguments is false) or about the arguments.
645 * The information includes the storage info (where the variable
646 * lives, in a register or in memory).
647 * The method is found by looking up what method has been emitted at
648 * the instruction address @ip.
649 * This is for use inside a debugger.
652 mono_debug_print_vars (gpointer ip
, gboolean only_arguments
)
654 MonoDomain
*domain
= mono_domain_get ();
655 MonoJitInfo
*ji
= mono_jit_info_table_find (domain
, ip
);
656 MonoDebugMethodJitInfo
*jit
;
662 jit
= mono_debug_find_method (jinfo_get_method (ji
), domain
);
666 if (only_arguments
) {
668 names
= g_new (char *, jit
->num_params
);
669 mono_method_get_param_names (jinfo_get_method (ji
), (const char **) names
);
671 print_var_info (jit
->this_var
, 0, "this", "Arg");
672 for (i
= 0; i
< jit
->num_params
; ++i
) {
673 print_var_info (&jit
->params
[i
], i
, names
[i
]? names
[i
]: "unknown name", "Arg");
677 for (i
= 0; i
< jit
->num_locals
; ++i
) {
678 print_var_info (&jit
->locals
[i
], i
, "", "Local");
681 mono_debug_free_method_jit_info (jit
);
685 * The old Debugger breakpoint interface.
687 * This interface is used to insert breakpoints on methods which are not yet JITed.
688 * The debugging code keeps a list of all such breakpoints and automatically inserts the
689 * breakpoint when the method is JITed.
692 static GPtrArray
*breakpoints
= NULL
;
695 mono_debugger_insert_breakpoint_full (MonoMethodDesc
*desc
)
697 static int last_breakpoint_id
= 0;
698 MiniDebugBreakpointInfo
*info
;
700 info
= g_new0 (MiniDebugBreakpointInfo
, 1);
702 info
->index
= ++last_breakpoint_id
;
705 breakpoints
= g_ptr_array_new ();
707 g_ptr_array_add (breakpoints
, info
);
712 /*FIXME This is part of the public API by accident, remove it from there when possible. */
714 mono_debugger_insert_breakpoint (const gchar
*method_name
, gboolean include_namespace
)
716 MonoMethodDesc
*desc
;
718 desc
= mono_method_desc_new (method_name
, include_namespace
);
722 return mono_debugger_insert_breakpoint_full (desc
);
725 /*FIXME This is part of the public API by accident, remove it from there when possible. */
727 mono_debugger_method_has_breakpoint (MonoMethod
*method
)
734 for (i
= 0; i
< breakpoints
->len
; i
++) {
735 MiniDebugBreakpointInfo
*info
= g_ptr_array_index (breakpoints
, i
);
737 if (!mono_method_desc_full_match (info
->desc
, method
))