2 #include <mono/jit/debug.h>
3 #include <mono/jit/debug-jit.h>
4 #include "debug-private.h"
7 mono_debug_codegen_breakpoint (guint8 **buf)
13 mono_debug_codegen_ret (guint8 **buf)
19 record_line_number (MonoDebugMethodInfo *minfo, guint32 address, guint32 offset, guint32 line)
21 MonoDebugLineNumberEntry *lne = g_new0 (MonoDebugLineNumberEntry, 1);
23 lne->address = address;
27 g_array_append_val (minfo->jit->line_numbers, *lne);
31 debug_generate_method_lines (AssemblyDebugInfo *info, MonoDebugMethodInfo *minfo, MonoFlowGraph* cfg)
33 guint32 st_address, st_line;
34 DebugMethodInfo *priv = minfo->user_data;
37 if (!priv || !info->moffsets)
40 minfo->jit->line_numbers = g_array_new (FALSE, TRUE, sizeof (MonoDebugLineNumberEntry));
42 st_line = priv->first_line;
43 st_address = minfo->jit->prologue_end;
45 /* This is the first actual code line of the method. */
46 record_line_number (minfo, st_address, 0, st_line);
48 /* start lines of basic blocks */
49 for (i = 0; i < cfg->block_count; ++i) {
52 for (j = 0; cfg->bblocks [i].forest && (j < cfg->bblocks [i].forest->len); ++j) {
53 MBTree *t = (MBTree *) g_ptr_array_index (cfg->bblocks [i].forest, j);
54 gint32 line_inc = 0, addr_inc;
57 st_line = priv->first_line;
61 addr_inc = t->addr - st_address;
62 st_address += addr_inc;
64 if (t->cli_addr != -1) {
65 int *lines = info->moffsets + st_line;
68 while ((*k != -1) && (*k < t->cli_addr))
76 if (t->cli_addr != -1)
77 record_line_number (minfo, st_address, t->cli_addr, st_line);
83 debug_update_il_offsets (AssemblyDebugInfo *info, MonoDebugMethodInfo *minfo, MonoFlowGraph* cfg)
85 MonoMethodHeader *header;
86 guint32 address, offset;
90 g_assert (info->symfile);
91 g_assert (!minfo->jit->line_numbers);
92 minfo->jit->line_numbers = g_array_new (FALSE, TRUE, sizeof (MonoDebugLineNumberEntry));
94 address = minfo->jit->prologue_end;
97 g_assert (((MonoMethodNormal*)minfo->method)->header);
98 header = ((MonoMethodNormal*)minfo->method)->header;
101 if (!strcmp (minfo->method->name, "Test") || !strcmp (minfo->method->name, "Main")) {
102 MonoMethodHeader *header = ((MonoMethodNormal*)minfo->method)->header;
105 mono_disassemble_code (minfo->jit->code_start, minfo->jit->code_size,
106 minfo->method->name);
108 printf ("\nDisassembly:\n%s\n", mono_disasm_code (
109 NULL, minfo->method, header->code, header->code + header->code_size));
110 g_message (G_STRLOC ": %x - %x", minfo->jit->prologue_end, minfo->jit->epilogue_begin);
114 _mono_debug_generate_line_number (minfo, address, offset, debug);
116 /* start lines of basic blocks */
117 for (i = 0; i < cfg->block_count; ++i) {
120 for (j = 0; cfg->bblocks [i].forest && (j < cfg->bblocks [i].forest->len); ++j) {
121 MBTree *t = (MBTree *) g_ptr_array_index (cfg->bblocks [i].forest, j);
123 if ((t->cli_addr == -1) || (t->cli_addr == offset) || (t->addr == address))
126 offset = t->cli_addr;
129 _mono_debug_generate_line_number (minfo, address, offset, debug);
133 _mono_debug_generate_line_number (minfo, minfo->jit->epilogue_begin, header->code_size, debug);
136 for (i = 0; i < minfo->jit->line_numbers->len; i++) {
137 MonoDebugLineNumberEntry lne = g_array_index (
138 minfo->jit->line_numbers, MonoDebugLineNumberEntry, i);
140 g_message (G_STRLOC ": %x,%x,%d", lne.address, lne.offset, lne.line);
144 if (minfo->jit->line_numbers->len) {
145 MonoDebugLineNumberEntry lne = g_array_index (
146 minfo->jit->line_numbers, MonoDebugLineNumberEntry, 0);
148 minfo->jit->prologue_end = lne.address;
153 il_offset_from_position (MonoFlowGraph *cfg, MonoPosition *pos)
158 if (pos->abs_pos == 0)
161 if (pos->pos.bid >= cfg->block_count)
164 bblock = &cfg->bblocks [pos->pos.bid];
165 if (pos->pos.tid >= bblock->forest->len)
168 tree = (MBTree *) g_ptr_array_index (bblock->forest, pos->pos.tid);
170 return tree->cli_addr;
174 mono_debug_add_method (MonoFlowGraph *cfg)
176 MonoMethod *method = cfg->method;
177 MonoClass *klass = method->klass;
178 AssemblyDebugInfo* info;
179 MonoDebugMethodJitInfo *jit;
180 MonoDebugMethodInfo *minfo;
183 if (!mono_debug_handle)
186 mono_class_init (klass);
188 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
189 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
190 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
191 (method->flags & METHOD_ATTRIBUTE_ABSTRACT))
194 info = _mono_debug_get_image (mono_debug_handle, klass->image);
197 if (method->wrapper_type != MONO_WRAPPER_NONE) {
198 DebugWrapperInfo *winfo = g_new0 (DebugWrapperInfo, 1);
200 winfo->method = method;
201 winfo->code_start = cfg->start;
202 winfo->code_size = cfg->epilogue_end;
204 g_hash_table_insert (info->wrapper_methods, method, winfo);
208 minfo = _mono_debug_lookup_method (method);
209 if (!minfo || minfo->jit)
214 mono_debug_handle->dirty = TRUE;
216 minfo->jit = jit = g_new0 (MonoDebugMethodJitInfo, 1);
217 jit->code_start = cfg->start;
218 jit->code_size = cfg->epilogue_end;
219 jit->prologue_end = cfg->prologue_end;
220 jit->epilogue_begin = cfg->epilog;
221 jit->num_params = method->signature->param_count;
222 jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
224 if (method->signature->hasthis) {
225 MonoVarInfo *ptr = ((MonoVarInfo *) cfg->varinfo->data) + cfg->args_start_index;
227 jit->this_var = g_new0 (MonoDebugVarInfo, 1);
228 jit->this_var->offset = ptr->offset;
229 jit->this_var->size = ptr->size;
232 for (i = 0; i < jit->num_params; i++) {
233 MonoVarInfo *ptr = ((MonoVarInfo *) cfg->varinfo->data) + cfg->args_start_index +
234 method->signature->hasthis;
236 jit->params [i].offset = ptr [i].offset;
237 jit->params [i].size = ptr [i].size;
240 debug_generate_method_lines (info, minfo, cfg);
241 if (info->format == MONO_DEBUG_FORMAT_MONO)
242 debug_update_il_offsets (info, minfo, cfg);
244 if (!method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
245 MonoMethodHeader *header = ((MonoMethodNormal*)method)->header;
246 MonoVarInfo *ptr = ((MonoVarInfo *) cfg->varinfo->data) + cfg->locals_start_index;
247 MonoDebugVarInfo *locals;
249 locals = g_new0 (MonoDebugVarInfo, header->num_locals);
250 for (i = 0; i < header->num_locals; i++) {
251 gint32 begin_offset, end_offset;
252 gint32 begin_scope, end_scope;
254 if (ptr [i].reg >= 0) {
255 locals [i].index = ptr [i].reg | MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER;
256 locals [i].offset = 0;
258 locals [i].offset = ptr [i].offset;
260 locals [i].size = ptr [i].size;
262 begin_offset = il_offset_from_position (cfg, &ptr [i].range.first_use);
263 end_offset = il_offset_from_position (cfg, &ptr [i].range.last_use);
267 if (begin_offset >= 0)
268 begin_scope = _mono_debug_address_from_il_offset (minfo, begin_offset);
272 end_scope = _mono_debug_address_from_il_offset (minfo, end_offset);
277 locals [i].begin_scope = begin_scope;
279 locals [i].begin_scope = jit->prologue_end;
281 locals [i].end_scope = end_scope;
283 locals [i].end_scope = jit->epilogue_begin;
286 jit->num_locals = header->num_locals;
287 jit->locals = locals;
291 mono_debug_symfile_add_method (info->symfile, method);
292 mono_debugger_event (MONO_DEBUGGER_EVENT_METHOD_ADDED, info->symfile, method);
295 mono_debug_unlock ();