1 #include <mono/jit/debug.h>
2 #include <mono/jit/debug-jit.h>
3 #include "debug-private.h"
6 mono_debug_codegen_breakpoint (guint8 **buf)
12 mono_debug_codegen_ret (guint8 **buf)
18 record_line_number (MonoDebugMethodInfo *minfo, guint32 address, guint32 offset, guint32 line)
20 MonoDebugLineNumberEntry *lne = g_new0 (MonoDebugLineNumberEntry, 1);
22 lne->address = address;
26 g_array_append_val (minfo->jit->line_numbers, *lne);
30 debug_generate_method_lines (AssemblyDebugInfo *info, MonoDebugMethodInfo *minfo, MonoFlowGraph* cfg)
32 guint32 st_address, st_line;
33 DebugMethodInfo *priv = minfo->user_data;
36 if (!priv || !info->moffsets)
39 minfo->jit->line_numbers = g_array_new (FALSE, TRUE, sizeof (MonoDebugLineNumberEntry));
41 st_line = priv->first_line;
42 st_address = minfo->jit->prologue_end;
44 /* This is the first actual code line of the method. */
45 record_line_number (minfo, st_address, 0, st_line);
47 /* start lines of basic blocks */
48 for (i = 0; i < cfg->block_count; ++i) {
51 for (j = 0; cfg->bblocks [i].forest && (j < cfg->bblocks [i].forest->len); ++j) {
52 MBTree *t = (MBTree *) g_ptr_array_index (cfg->bblocks [i].forest, j);
53 gint32 line_inc = 0, addr_inc;
56 st_line = priv->first_line;
60 addr_inc = t->addr - st_address;
61 st_address += addr_inc;
63 if (t->cli_addr != -1) {
64 int *lines = info->moffsets + st_line;
67 while ((*k != -1) && (*k < t->cli_addr))
75 if (t->cli_addr != -1)
76 record_line_number (minfo, st_address, t->cli_addr, st_line);
82 debug_update_il_offsets (AssemblyDebugInfo *info, MonoDebugMethodInfo *minfo, MonoFlowGraph* cfg)
84 MonoMethodHeader *header;
85 guint32 address, offset;
89 g_assert (info->symfile);
90 g_assert (!minfo->jit->line_numbers);
91 minfo->jit->line_numbers = g_array_new (FALSE, TRUE, sizeof (MonoDebugLineNumberEntry));
93 address = minfo->jit->prologue_end;
96 g_assert (((MonoMethodNormal*)minfo->method)->header);
97 header = ((MonoMethodNormal*)minfo->method)->header;
100 if (!strcmp (minfo->method->name, "Test") || !strcmp (minfo->method->name, "Main")) {
101 MonoMethodHeader *header = ((MonoMethodNormal*)minfo->method)->header;
104 mono_disassemble_code (minfo->jit->code_start, minfo->jit->code_size,
105 minfo->method->name);
107 printf ("\nDisassembly:\n%s\n", mono_disasm_code (
108 NULL, minfo->method, header->code, header->code + header->code_size));
109 g_message (G_STRLOC ": %x - %x", minfo->jit->prologue_end, minfo->jit->epilogue_begin);
113 _mono_debug_generate_line_number (minfo, address, offset, debug);
115 /* start lines of basic blocks */
116 for (i = 0; i < cfg->block_count; ++i) {
119 for (j = 0; cfg->bblocks [i].forest && (j < cfg->bblocks [i].forest->len); ++j) {
120 MBTree *t = (MBTree *) g_ptr_array_index (cfg->bblocks [i].forest, j);
122 if ((t->cli_addr == -1) || (t->cli_addr == offset) || (t->addr == address))
125 offset = t->cli_addr;
128 _mono_debug_generate_line_number (minfo, address, offset, debug);
132 _mono_debug_generate_line_number (minfo, minfo->jit->epilogue_begin, header->code_size, debug);
135 for (i = 0; i < minfo->jit->line_numbers->len; i++) {
136 MonoDebugLineNumberEntry lne = g_array_index (
137 minfo->jit->line_numbers, MonoDebugLineNumberEntry, i);
139 g_message (G_STRLOC ": %x,%x,%d", lne.address, lne.offset, lne.line);
143 if (minfo->jit->line_numbers->len) {
144 MonoDebugLineNumberEntry lne = g_array_index (
145 minfo->jit->line_numbers, MonoDebugLineNumberEntry, 0);
147 minfo->jit->prologue_end = lne.address;
152 il_offset_from_position (MonoFlowGraph *cfg, MonoPosition *pos)
157 if (pos->abs_pos == 0)
160 if (pos->pos.bid >= cfg->block_count)
163 bblock = &cfg->bblocks [pos->pos.bid];
164 if (pos->pos.tid >= bblock->forest->len)
167 tree = (MBTree *) g_ptr_array_index (bblock->forest, pos->pos.tid);
169 return tree->cli_addr;
173 mono_debug_add_method (MonoFlowGraph *cfg)
175 MonoMethod *method = cfg->method;
176 MonoClass *klass = method->klass;
177 AssemblyDebugInfo* info;
178 MonoDebugMethodJitInfo *jit;
179 MonoDebugMethodInfo *minfo;
182 if (!mono_debug_handle)
185 mono_class_init (klass);
187 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
188 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
189 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
190 (method->flags & METHOD_ATTRIBUTE_ABSTRACT))
193 info = _mono_debug_get_image (mono_debug_handle, klass->image);
196 if (method->wrapper_type != MONO_WRAPPER_NONE) {
197 DebugWrapperInfo *winfo = g_new0 (DebugWrapperInfo, 1);
199 winfo->method = method;
200 winfo->code_start = cfg->start;
201 winfo->code_size = cfg->epilogue_end;
203 g_hash_table_insert (info->wrapper_methods, method, winfo);
207 minfo = _mono_debug_lookup_method (method);
208 if (!minfo || minfo->jit)
213 mono_debug_handle->dirty = TRUE;
215 minfo->jit = jit = g_new0 (MonoDebugMethodJitInfo, 1);
216 jit->code_start = cfg->start;
217 jit->code_size = cfg->epilogue_end;
218 jit->prologue_end = cfg->prologue_end;
219 jit->epilogue_begin = cfg->epilog;
220 jit->num_params = method->signature->param_count;
221 jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
223 if (method->signature->hasthis) {
224 MonoVarInfo *ptr = ((MonoVarInfo *) cfg->varinfo->data) + cfg->args_start_index;
226 jit->this_var = g_new0 (MonoDebugVarInfo, 1);
227 jit->this_var->offset = ptr->offset;
228 jit->this_var->size = ptr->size;
231 for (i = 0; i < jit->num_params; i++) {
232 MonoVarInfo *ptr = ((MonoVarInfo *) cfg->varinfo->data) + cfg->args_start_index +
233 method->signature->hasthis;
235 jit->params [i].offset = ptr [i].offset;
236 jit->params [i].size = ptr [i].size;
239 debug_generate_method_lines (info, minfo, cfg);
240 if (info->format == MONO_DEBUG_FORMAT_MONO)
241 debug_update_il_offsets (info, minfo, cfg);
243 if (!method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
244 MonoMethodHeader *header = ((MonoMethodNormal*)method)->header;
245 MonoVarInfo *ptr = ((MonoVarInfo *) cfg->varinfo->data) + cfg->locals_start_index;
246 MonoDebugVarInfo *locals;
248 locals = g_new0 (MonoDebugVarInfo, header->num_locals);
249 for (i = 0; i < header->num_locals; i++) {
250 gint32 begin_offset, end_offset;
251 gint32 begin_scope, end_scope;
253 if (ptr [i].reg >= 0) {
254 locals [i].index = ptr [i].reg | MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER;
255 locals [i].offset = 0;
257 locals [i].offset = ptr [i].offset;
259 locals [i].size = ptr [i].size;
261 begin_offset = il_offset_from_position (cfg, &ptr [i].range.first_use);
262 end_offset = il_offset_from_position (cfg, &ptr [i].range.last_use);
266 if (begin_offset >= 0)
267 begin_scope = _mono_debug_address_from_il_offset (minfo, begin_offset);
271 end_scope = _mono_debug_address_from_il_offset (minfo, end_offset);
276 locals [i].begin_scope = begin_scope;
278 locals [i].begin_scope = jit->prologue_end;
280 locals [i].end_scope = end_scope;
282 locals [i].end_scope = jit->epilogue_begin;
285 jit->num_locals = header->num_locals;
286 jit->locals = locals;
290 mono_debug_symfile_add_method (info->symfile, method);
291 mono_debugger_event (MONO_DEBUGGER_EVENT_METHOD_ADDED, info->symfile, method);
294 mono_debug_unlock ();