3 * Mini-specific debugging stuff.
6 * Martin Baulig (martin@ximian.com)
8 * (C) 2003 Ximian, Inc.
12 #include "mini-runtime.h"
15 #include <mono/metadata/verify.h>
16 #include <mono/metadata/mono-config.h>
17 #include <mono/metadata/mono-debug.h>
18 #include <mono/metadata/appdomain.h>
19 #include <mono/metadata/threads-types.h>
21 #include <mono/metadata/debug-internals.h>
23 #include <mono/utils/valgrind.h>
28 } MiniDebugBreakpointInfo
;
32 MonoDebugMethodJitInfo
*jit
;
34 guint32 has_line_numbers
;
35 guint32 breakpoint_id
;
36 } MiniDebugMethodInfo
;
39 record_line_number (MiniDebugMethodInfo
*info
, guint32 address
, guint32 offset
)
41 MonoDebugLineNumberEntry lne
;
43 lne
.native_offset
= address
;
44 lne
.il_offset
= offset
;
46 g_array_append_val (info
->line_numbers
, lne
);
51 mono_debug_init_method (MonoCompile
*cfg
, MonoBasicBlock
*start_block
, guint32 breakpoint_id
)
53 MiniDebugMethodInfo
*info
;
55 if (!mono_debug_enabled ())
58 info
= g_new0 (MiniDebugMethodInfo
, 1);
59 info
->breakpoint_id
= breakpoint_id
;
61 cfg
->debug_info
= info
;
65 mono_debug_open_method (MonoCompile
*cfg
)
67 MiniDebugMethodInfo
*info
;
68 MonoDebugMethodJitInfo
*jit
;
69 MonoMethodHeader
*header
;
71 info
= (MiniDebugMethodInfo
*) cfg
->debug_info
;
75 mono_class_init_internal (cfg
->method
->klass
);
80 info
->jit
= jit
= g_new0 (MonoDebugMethodJitInfo
, 1);
81 info
->line_numbers
= g_array_new (FALSE
, TRUE
, sizeof (MonoDebugLineNumberEntry
));
82 jit
->num_locals
= header
->num_locals
;
83 jit
->locals
= g_new0 (MonoDebugVarInfo
, jit
->num_locals
);
87 write_variable (MonoInst
*inst
, MonoDebugVarInfo
*var
)
89 var
->type
= inst
->inst_vtype
;
91 if (inst
->opcode
== OP_REGVAR
)
92 var
->index
= inst
->dreg
| MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER
;
93 else if (inst
->flags
& MONO_INST_IS_DEAD
)
94 var
->index
= MONO_DEBUG_VAR_ADDRESS_MODE_DEAD
;
95 else if (inst
->opcode
== OP_REGOFFSET
) {
96 /* the debug interface needs fixing to allow 0(%base) address */
97 var
->index
= inst
->inst_basereg
| MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET
;
98 var
->offset
= inst
->inst_offset
;
99 } else if (inst
->opcode
== OP_GSHAREDVT_ARG_REGOFFSET
) {
100 var
->index
= inst
->inst_basereg
| MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET_INDIR
;
101 var
->offset
= inst
->inst_offset
;
102 } else if (inst
->opcode
== OP_GSHAREDVT_LOCAL
) {
103 var
->index
= inst
->inst_imm
| MONO_DEBUG_VAR_ADDRESS_MODE_GSHAREDVT_LOCAL
;
104 } else if (inst
->opcode
== OP_VTARG_ADDR
) {
107 vtaddr
= inst
->inst_left
;
108 g_assert (vtaddr
->opcode
== OP_REGOFFSET
);
109 var
->offset
= vtaddr
->inst_offset
;
110 var
->index
= vtaddr
->inst_basereg
| MONO_DEBUG_VAR_ADDRESS_MODE_VTADDR
;
112 g_assert_not_reached ();
117 * mono_debug_add_vg_method:
119 * Register symbol information for the method with valgrind
122 mono_debug_add_vg_method (MonoMethod
*method
, MonoDebugMethodJitInfo
*jit
)
124 #ifdef VALGRIND_ADD_LINE_INFO
126 MonoMethodHeader
*header
;
127 MonoDebugMethodInfo
*minfo
;
129 char *filename
= NULL
;
130 guint32 address
, line_number
;
131 const char *full_name
;
135 if (!RUNNING_ON_VALGRIND
)
138 header
= mono_method_get_header_checked (method
, error
);
139 mono_error_assert_ok (error
); /* FIXME don't swallow the error */
141 full_name
= mono_method_full_name (method
, TRUE
);
143 addresses
= g_new0 (guint32
, header
->code_size
+ 1);
144 lines
= g_new0 (guint32
, header
->code_size
+ 1);
147 * Very simple code to convert the addr->offset mappings that mono has
148 * into [addr-addr] ->line number mappings.
151 minfo
= mono_debug_lookup_method (method
);
153 /* Create offset->line number mapping */
154 for (i
= 0; i
< header
->code_size
; ++i
) {
155 MonoDebugSourceLocation
*location
;
157 location
= mono_debug_method_lookup_location (minfo
, i
);
161 lines
[i
] = location
.row
;
163 filename
= location
.source_file
;
165 mono_debug_free_source_location (location
);
169 /* Create address->offset mapping */
170 for (i
= 0; i
< jit
->num_line_numbers
; ++i
) {
171 MonoDebugLineNumberEntry
*lne
= jit
->line_numbers
[i
];
173 g_assert (lne
->offset
<= header
->code_size
);
175 if ((addresses
[lne
->offset
] == 0) || (lne
->address
< addresses
[lne
->offset
]))
176 addresses
[lne
->offset
] = lne
->address
;
178 /* Fill out missing addresses */
180 for (i
= 0; i
< header
->code_size
; ++i
) {
181 if (addresses
[i
] == 0)
182 addresses
[i
] = address
;
184 address
= addresses
[i
];
190 while (i
< header
->code_size
) {
191 if (lines
[i
] == line_number
)
194 if (line_number
> 0) {
195 //g_assert (addresses [i] - 1 >= address);
197 if (addresses
[i
] - 1 >= address
) {
198 VALGRIND_ADD_LINE_INFO (jit
->code_start
+ address
, jit
->code_start
+ addresses
[i
] - 1, filename
, line_number
);
199 //printf ("[%d-%d] -> %d.\n", address, addresses [i] - 1, line_number);
202 address
= addresses
[i
];
203 line_number
= lines
[i
];
207 if (line_number
> 0) {
208 VALGRIND_ADD_LINE_INFO (jit
->code_start
+ address
, jit
->code_start
+ jit
->code_size
- 1, filename
, line_number
);
209 //printf ("[%d-%d] -> %d.\n", address, jit->code_size - 1, line_number);
212 VALGRIND_ADD_SYMBOL (jit
->code_start
, jit
->code_size
, full_name
);
216 mono_metadata_free_mh (header
);
217 #endif /* VALGRIND_ADD_LINE_INFO */
221 mono_debug_close_method (MonoCompile
*cfg
)
223 MiniDebugMethodInfo
*info
;
224 MonoDebugMethodJitInfo
*jit
;
225 MonoMethodHeader
*header
;
226 MonoMethodSignature
*sig
;
230 info
= (MiniDebugMethodInfo
*) cfg
->debug_info
;
231 if (!info
|| !info
->jit
) {
237 method
= cfg
->method
;
238 header
= cfg
->header
;
239 sig
= mono_method_signature_internal (method
);
242 jit
->code_start
= cfg
->native_code
;
243 jit
->epilogue_begin
= cfg
->epilog_begin
;
244 jit
->code_size
= cfg
->code_len
;
245 jit
->has_var_info
= mini_debug_options
.mdb_optimizations
|| MONO_CFG_PROFILE_CALL_CONTEXT (cfg
);
247 if (jit
->epilogue_begin
)
248 record_line_number (info
, jit
->epilogue_begin
, header
->code_size
);
250 if (jit
->has_var_info
) {
251 jit
->num_params
= sig
->param_count
;
252 jit
->params
= g_new0 (MonoDebugVarInfo
, jit
->num_params
);
254 for (i
= 0; i
< jit
->num_locals
; i
++)
255 write_variable (cfg
->locals
[i
], &jit
->locals
[i
]);
258 jit
->this_var
= g_new0 (MonoDebugVarInfo
, 1);
259 write_variable (cfg
->args
[0], jit
->this_var
);
262 for (i
= 0; i
< jit
->num_params
; i
++)
263 write_variable (cfg
->args
[i
+ sig
->hasthis
], &jit
->params
[i
]);
265 if (cfg
->gsharedvt_info_var
) {
266 jit
->gsharedvt_info_var
= g_new0 (MonoDebugVarInfo
, 1);
267 jit
->gsharedvt_locals_var
= g_new0 (MonoDebugVarInfo
, 1);
268 write_variable (cfg
->gsharedvt_info_var
, jit
->gsharedvt_info_var
);
269 write_variable (cfg
->gsharedvt_locals_var
, jit
->gsharedvt_locals_var
);
273 jit
->num_line_numbers
= info
->line_numbers
->len
;
274 jit
->line_numbers
= g_new0 (MonoDebugLineNumberEntry
, jit
->num_line_numbers
);
276 for (i
= 0; i
< jit
->num_line_numbers
; i
++)
277 jit
->line_numbers
[i
] = g_array_index (info
->line_numbers
, MonoDebugLineNumberEntry
, i
);
279 mono_debug_add_method (cfg
->method_to_register
, jit
, cfg
->domain
);
281 mono_debug_add_vg_method (method
, jit
);
283 mono_debug_free_method_jit_info (jit
);
284 mono_debug_free_method (cfg
);
288 mono_debug_free_method (MonoCompile
*cfg
)
290 MiniDebugMethodInfo
*info
;
292 info
= (MiniDebugMethodInfo
*) cfg
->debug_info
;
294 if (info
->line_numbers
)
295 g_array_free (info
->line_numbers
, TRUE
);
297 cfg
->debug_info
= NULL
;
302 mono_debug_record_line_number (MonoCompile
*cfg
, MonoInst
*ins
, guint32 address
)
304 MiniDebugMethodInfo
*info
;
305 MonoMethodHeader
*header
;
308 info
= (MiniDebugMethodInfo
*) cfg
->debug_info
;
309 if (!info
|| !info
->jit
|| !ins
->cil_code
)
312 header
= cfg
->header
;
315 if ((ins
->cil_code
< header
->code
) ||
316 (ins
->cil_code
> header
->code
+ header
->code_size
))
319 offset
= ins
->cil_code
- header
->code
;
320 if (!info
->has_line_numbers
) {
321 info
->jit
->prologue_end
= address
;
322 info
->has_line_numbers
= TRUE
;
325 record_line_number (info
, address
, offset
);
329 mono_debug_open_block (MonoCompile
*cfg
, MonoBasicBlock
*bb
, guint32 address
)
331 MiniDebugMethodInfo
*info
;
332 MonoMethodHeader
*header
;
335 info
= (MiniDebugMethodInfo
*) cfg
->debug_info
;
336 if (!info
|| !info
->jit
|| !bb
->cil_code
)
339 header
= cfg
->header
;
342 if ((bb
->cil_code
< header
->code
) ||
343 (bb
->cil_code
> header
->code
+ header
->code_size
))
346 offset
= bb
->cil_code
- header
->code
;
347 if (!info
->has_line_numbers
) {
348 info
->jit
->prologue_end
= address
;
349 info
->has_line_numbers
= TRUE
;
352 record_line_number (info
, address
, offset
);
356 encode_value (gint32 value
, guint8
*buf
, guint8
**endbuf
)
360 //printf ("ENCODE: %d 0x%x.\n", value, value);
363 * Same encoding as the one used in the metadata, extended to handle values
364 * greater than 0x1fffffff.
366 if ((value
>= 0) && (value
<= 127))
368 else if ((value
>= 0) && (value
<= 16383)) {
369 p
[0] = 0x80 | (value
>> 8);
370 p
[1] = value
& 0xff;
372 } else if ((value
>= 0) && (value
<= 0x1fffffff)) {
373 p
[0] = (value
>> 24) | 0xc0;
374 p
[1] = (value
>> 16) & 0xff;
375 p
[2] = (value
>> 8) & 0xff;
376 p
[3] = value
& 0xff;
381 p
[1] = (value
>> 24) & 0xff;
382 p
[2] = (value
>> 16) & 0xff;
383 p
[3] = (value
>> 8) & 0xff;
384 p
[4] = value
& 0xff;
392 decode_value (guint8
*ptr
, guint8
**rptr
)
397 if ((b
& 0x80) == 0){
400 } else if ((b
& 0x40) == 0){
401 len
= ((b
& 0x3f) << 8 | ptr
[1]);
403 } else if (b
!= 0xff) {
404 len
= ((b
& 0x1f) << 24) |
411 len
= (ptr
[1] << 24) | (ptr
[2] << 16) | (ptr
[3] << 8) | ptr
[4];
417 //printf ("DECODE: %d.\n", len);
422 serialize_variable (MonoDebugVarInfo
*var
, guint8
*p
, guint8
**endbuf
)
424 guint32 flags
= var
->index
& MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS
;
426 encode_value (var
->index
, p
, &p
);
429 case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER
:
431 case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET
:
432 case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET_INDIR
:
433 case MONO_DEBUG_VAR_ADDRESS_MODE_VTADDR
:
434 encode_value (var
->offset
, p
, &p
);
436 case MONO_DEBUG_VAR_ADDRESS_MODE_GSHAREDVT_LOCAL
:
437 case MONO_DEBUG_VAR_ADDRESS_MODE_DEAD
:
440 g_assert_not_reached ();
446 mono_debug_serialize_debug_info (MonoCompile
*cfg
, guint8
**out_buf
, guint32
*buf_len
)
448 MonoDebugMethodJitInfo
*jit
;
449 guint32 size
, prev_offset
, prev_native_offset
;
453 /* Can't use cfg->debug_info as it is freed by close_method () */
454 jit
= mono_debug_find_method (cfg
->method
, mono_domain_get ());
460 size
= ((jit
->num_params
+ jit
->num_locals
+ 1) * 10) + (jit
->num_line_numbers
* 10) + 64;
461 p
= buf
= (guint8
*)g_malloc (size
);
462 encode_value (jit
->epilogue_begin
, p
, &p
);
463 encode_value (jit
->prologue_end
, p
, &p
);
464 encode_value (jit
->code_size
, p
, &p
);
465 encode_value (jit
->has_var_info
, p
, &p
);
467 if (jit
->has_var_info
) {
468 encode_value (jit
->num_locals
, p
, &p
);
470 for (i
= 0; i
< jit
->num_params
; ++i
)
471 serialize_variable (&jit
->params
[i
], p
, &p
);
474 serialize_variable (jit
->this_var
, p
, &p
);
476 for (i
= 0; i
< jit
->num_locals
; i
++)
477 serialize_variable (&jit
->locals
[i
], p
, &p
);
479 if (jit
->gsharedvt_info_var
) {
480 encode_value (1, p
, &p
);
481 serialize_variable (jit
->gsharedvt_info_var
, p
, &p
);
482 serialize_variable (jit
->gsharedvt_locals_var
, p
, &p
);
484 encode_value (0, p
, &p
);
488 encode_value (jit
->num_line_numbers
, p
, &p
);
491 prev_native_offset
= 0;
492 for (i
= 0; i
< jit
->num_line_numbers
; ++i
) {
493 /* Sometimes, the offset values are not in increasing order */
494 MonoDebugLineNumberEntry
*lne
= &jit
->line_numbers
[i
];
495 encode_value (lne
->il_offset
- prev_offset
, p
, &p
);
496 encode_value (lne
->native_offset
- prev_native_offset
, p
, &p
);
497 prev_offset
= lne
->il_offset
;
498 prev_native_offset
= lne
->native_offset
;
501 g_assert (p
- buf
< size
);
508 deserialize_variable (MonoDebugVarInfo
*var
, guint8
*p
, guint8
**endbuf
)
512 var
->index
= decode_value (p
, &p
);
514 flags
= var
->index
& MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS
;
517 case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER
:
519 case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET
:
520 case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET_INDIR
:
521 case MONO_DEBUG_VAR_ADDRESS_MODE_VTADDR
:
522 var
->offset
= decode_value (p
, &p
);
524 case MONO_DEBUG_VAR_ADDRESS_MODE_GSHAREDVT_LOCAL
:
525 case MONO_DEBUG_VAR_ADDRESS_MODE_DEAD
:
528 g_assert_not_reached ();
533 static MonoDebugMethodJitInfo
*
534 deserialize_debug_info (MonoMethod
*method
, guint8
*code_start
, guint8
*buf
, guint32 buf_len
)
536 gint32 offset
, native_offset
, prev_offset
, prev_native_offset
;
537 MonoDebugMethodJitInfo
*jit
;
541 jit
= g_new0 (MonoDebugMethodJitInfo
, 1);
542 jit
->code_start
= code_start
;
545 jit
->epilogue_begin
= decode_value (p
, &p
);
546 jit
->prologue_end
= decode_value (p
, &p
);
547 jit
->code_size
= decode_value (p
, &p
);
548 jit
->has_var_info
= decode_value (p
, &p
);
550 if (jit
->has_var_info
) {
551 jit
->num_locals
= decode_value (p
, &p
);
553 jit
->num_params
= mono_method_signature_internal (method
)->param_count
;
554 jit
->params
= g_new0 (MonoDebugVarInfo
, jit
->num_params
);
555 jit
->locals
= g_new0 (MonoDebugVarInfo
, jit
->num_locals
);
557 for (i
= 0; i
< jit
->num_params
; ++i
)
558 deserialize_variable (&jit
->params
[i
], p
, &p
);
560 if (mono_method_signature_internal (method
)->hasthis
) {
561 jit
->this_var
= g_new0 (MonoDebugVarInfo
, 1);
562 deserialize_variable (jit
->this_var
, p
, &p
);
565 for (i
= 0; i
< jit
->num_locals
; i
++)
566 deserialize_variable (&jit
->locals
[i
], p
, &p
);
568 if (decode_value (p
, &p
)) {
569 jit
->gsharedvt_info_var
= g_new0 (MonoDebugVarInfo
, 1);
570 jit
->gsharedvt_locals_var
= g_new0 (MonoDebugVarInfo
, 1);
571 deserialize_variable (jit
->gsharedvt_info_var
, p
, &p
);
572 deserialize_variable (jit
->gsharedvt_locals_var
, p
, &p
);
576 jit
->num_line_numbers
= decode_value (p
, &p
);
577 jit
->line_numbers
= g_new0 (MonoDebugLineNumberEntry
, jit
->num_line_numbers
);
580 prev_native_offset
= 0;
581 for (i
= 0; i
< jit
->num_line_numbers
; ++i
) {
582 MonoDebugLineNumberEntry
*lne
= &jit
->line_numbers
[i
];
584 offset
= prev_offset
+ decode_value (p
, &p
);
585 native_offset
= prev_native_offset
+ decode_value (p
, &p
);
587 lne
->native_offset
= native_offset
;
588 lne
->il_offset
= offset
;
590 prev_offset
= offset
;
591 prev_native_offset
= native_offset
;
598 mono_debug_add_aot_method (MonoDomain
*domain
, MonoMethod
*method
, guint8
*code_start
,
599 guint8
*debug_info
, guint32 debug_info_len
)
601 MonoDebugMethodJitInfo
*jit
;
603 if (!mono_debug_enabled ())
606 if ((method
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) ||
607 (method
->iflags
& METHOD_IMPL_ATTRIBUTE_RUNTIME
) ||
608 (method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) ||
609 (method
->flags
& METHOD_ATTRIBUTE_ABSTRACT
) ||
610 (method
->wrapper_type
!= MONO_WRAPPER_NONE
))
613 if (debug_info_len
== 0)
616 jit
= deserialize_debug_info (method
, code_start
, debug_info
, debug_info_len
);
618 mono_debug_add_method (method
, jit
, domain
);
620 mono_debug_add_vg_method (method
, jit
);
622 mono_debug_free_method_jit_info (jit
);
626 print_var_info (MonoDebugVarInfo
*info
, int idx
, const char *name
, const char *type
)
628 switch (info
->index
& MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS
) {
629 case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER
:
630 g_print ("%s %s (%d) in register %s\n", type
, name
, idx
, mono_arch_regname (info
->index
& (~MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS
)));
632 case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET
:
633 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
);
635 case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET_INDIR
:
636 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
);
638 case MONO_DEBUG_VAR_ADDRESS_MODE_GSHAREDVT_LOCAL
:
639 g_print ("%s %s (%d) gsharedvt local.\n", type
, name
, idx
);
641 case MONO_DEBUG_VAR_ADDRESS_MODE_VTADDR
:
642 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
);
644 case MONO_DEBUG_VAR_ADDRESS_MODE_TWO_REGISTERS
:
646 g_assert_not_reached ();
651 * mono_debug_print_locals:
653 * Prints to stdout the information about the local variables in
654 * a method (if \p only_arguments is false) or about the arguments.
655 * The information includes the storage info (where the variable
656 * lives, in a register or in memory).
657 * The method is found by looking up what method has been emitted at
658 * the instruction address \p ip.
659 * This is for use inside a debugger.
662 mono_debug_print_vars (gpointer ip
, gboolean only_arguments
)
664 MonoDomain
*domain
= mono_domain_get ();
665 MonoJitInfo
*ji
= mono_jit_info_table_find (domain
, ip
);
666 MonoDebugMethodJitInfo
*jit
;
672 jit
= mono_debug_find_method (jinfo_get_method (ji
), domain
);
676 if (only_arguments
) {
678 names
= g_new (char *, jit
->num_params
);
679 mono_method_get_param_names (jinfo_get_method (ji
), (const char **) names
);
681 print_var_info (jit
->this_var
, 0, "this", "Arg");
682 for (i
= 0; i
< jit
->num_params
; ++i
) {
683 print_var_info (&jit
->params
[i
], i
, names
[i
]? names
[i
]: "unknown name", "Arg");
687 for (i
= 0; i
< jit
->num_locals
; ++i
) {
688 print_var_info (&jit
->locals
[i
], i
, "", "Local");
691 mono_debug_free_method_jit_info (jit
);
695 * The old Debugger breakpoint interface.
697 * This interface is used to insert breakpoints on methods which are not yet JITed.
698 * The debugging code keeps a list of all such breakpoints and automatically inserts the
699 * breakpoint when the method is JITed.
702 static GPtrArray
*breakpoints
;
705 mono_debugger_insert_breakpoint_full (MonoMethodDesc
*desc
)
707 static int last_breakpoint_id
= 0;
708 MiniDebugBreakpointInfo
*info
;
710 info
= g_new0 (MiniDebugBreakpointInfo
, 1);
712 info
->index
= ++last_breakpoint_id
;
715 breakpoints
= g_ptr_array_new ();
717 g_ptr_array_add (breakpoints
, info
);
722 /*FIXME This is part of the public API by accident, remove it from there when possible. */
724 mono_debugger_insert_breakpoint (const gchar
*method_name
, gboolean include_namespace
)
726 MonoMethodDesc
*desc
;
728 desc
= mono_method_desc_new (method_name
, include_namespace
);
732 return mono_debugger_insert_breakpoint_full (desc
);
735 /*FIXME This is part of the public API by accident, remove it from there when possible. */
737 mono_debugger_method_has_breakpoint (MonoMethod
*method
)
744 for (i
= 0; i
< breakpoints
->len
; i
++) {
745 MiniDebugBreakpointInfo
*info
= (MiniDebugBreakpointInfo
*)g_ptr_array_index (breakpoints
, i
);
747 if (!mono_method_desc_full_match (info
->desc
, method
))