2 * debug-mini.c: Mini-specific debugging stuff.
5 * Martin Baulig (martin@ximian.com)
7 * (C) 2003 Ximian, Inc.
12 #include <mono/metadata/verify.h>
13 #include <mono/metadata/mono-config.h>
14 #include <mono/metadata/mono-debug.h>
15 /* mono-debug-debugger.h nneds config.h to work... */
17 #include <mono/metadata/mono-debug-debugger.h>
20 record_line_number (MonoDebugMethodJitInfo *jit, guint32 address, guint32 offset)
22 MonoDebugLineNumberEntry *lne = g_new0 (MonoDebugLineNumberEntry, 1);
24 lne->address = address;
27 g_array_append_val (jit->line_numbers, *lne);
32 MonoDebugMethodJitInfo *jit;
33 guint32 has_line_numbers;
34 guint32 breakpoint_id;
35 } MiniDebugMethodInfo;
38 mono_debug_init_method (MonoCompile *cfg, MonoBasicBlock *start_block, guint32 breakpoint_id)
40 MonoMethod *method = cfg->method;
41 MiniDebugMethodInfo *info;
43 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
46 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
47 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
48 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
49 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
50 (method->wrapper_type != MONO_WRAPPER_NONE))
53 info = g_new0 (MiniDebugMethodInfo, 1);
54 info->breakpoint_id = breakpoint_id;
56 cfg->debug_info = info;
60 mono_debug_open_method (MonoCompile *cfg)
62 MiniDebugMethodInfo *info;
63 MonoDebugMethodJitInfo *jit;
64 MonoMethodHeader *header;
66 info = (MiniDebugMethodInfo *) cfg->debug_info;
70 mono_class_init (cfg->method->klass);
72 g_assert (((MonoMethodNormal*)cfg->method)->header);
73 header = ((MonoMethodNormal*)cfg->method)->header;
75 info->jit = jit = g_new0 (MonoDebugMethodJitInfo, 1);
76 jit->line_numbers = g_array_new (FALSE, TRUE, sizeof (MonoDebugLineNumberEntry));
77 jit->num_locals = header->num_locals;
78 jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
82 write_variable (MonoInst *inst, MonoDebugVarInfo *var)
84 if (inst->opcode == OP_REGVAR)
85 var->index = inst->dreg | MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER;
87 /* the debug interface needs fixing to allow 0(%base) address */
88 var->index = inst->inst_basereg | MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET;
89 var->offset = inst->inst_offset;
94 mono_debug_close_method (MonoCompile *cfg)
96 MiniDebugMethodInfo *info;
97 MonoDebugMethodJitInfo *jit;
98 MonoMethodHeader *header;
102 info = (MiniDebugMethodInfo *) cfg->debug_info;
103 if (!info || !info->jit)
106 method = cfg->method;
107 header = ((MonoMethodNormal*)method)->header;
110 jit->code_start = cfg->native_code;
111 jit->epilogue_begin = cfg->epilog_begin;
112 jit->code_size = cfg->code_len;
114 record_line_number (jit, jit->epilogue_begin, header->code_size);
116 jit->num_params = method->signature->param_count;
117 jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
119 for (i = 0; i < jit->num_locals; i++)
120 write_variable (cfg->varinfo [cfg->locals_start + i], &jit->locals [i]);
122 if (method->signature->hasthis) {
123 jit->this_var = g_new0 (MonoDebugVarInfo, 1);
124 write_variable (cfg->varinfo [0], jit->this_var);
127 for (i = 0; i < jit->num_params; i++)
128 write_variable (cfg->varinfo [i + method->signature->hasthis], &jit->params [i]);
130 mono_debug_add_method (method, jit, cfg->domain);
132 if (info->breakpoint_id)
133 mono_debugger_breakpoint_callback (method, info->breakpoint_id);
137 mono_debug_record_line_number (MonoCompile *cfg, MonoInst *ins, guint32 address)
139 MiniDebugMethodInfo *info;
140 MonoMethodHeader *header;
143 info = (MiniDebugMethodInfo *) cfg->debug_info;
144 if (!info || !info->jit || !ins->cil_code)
147 g_assert (((MonoMethodNormal*)cfg->method)->header);
148 header = ((MonoMethodNormal*)cfg->method)->header;
150 if ((ins->cil_code < header->code) ||
151 (ins->cil_code > header->code + header->code_size))
154 offset = ins->cil_code - header->code;
155 if (!info->has_line_numbers) {
156 info->jit->prologue_end = address;
157 info->has_line_numbers = TRUE;
160 record_line_number (info->jit, address, offset);
164 encode_value (guint32 value, char *buf, char **endbuf)
168 //printf ("ENCODE: %d 0x%x.\n", value, value);
171 * Same encoding as the one used in the metadata, extended to handle values
172 * greater than 0x1fffffff.
176 else if (value <= 16384) {
177 p [0] = 0x80 | (value >> 8);
178 p [1] = value & 0xff;
180 } else if (value <= 0x1fffffff) {
181 p [0] = (value >> 24) | 0xc0;
182 p [1] = (value >> 16) & 0xff;
183 p [2] = (value >> 8) & 0xff;
184 p [3] = value & 0xff;
189 p [1] = (value >> 24) & 0xff;
190 p [2] = (value >> 16) & 0xff;
191 p [3] = (value >> 8) & 0xff;
192 p [4] = value & 0xff;
199 static inline guint32
200 decode_value (char *_ptr, char **rptr)
202 unsigned char *ptr = (unsigned char *) _ptr;
203 unsigned char b = *ptr;
206 if ((b & 0x80) == 0){
209 } else if ((b & 0x40) == 0){
210 len = ((b & 0x3f) << 8 | ptr [1]);
212 } else if (b != 0xff) {
213 len = ((b & 0x1f) << 24) |
220 len = (ptr [0] << 24) | (ptr [1] << 16) | (ptr [2] << 8) | ptr [3];
226 //printf ("DECODE: %d.\n", len);
231 serialize_variable (MonoDebugVarInfo *var, char *p, char **endbuf)
233 guint32 flags = var->index & MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
236 case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER:
237 encode_value (var->index, p, &p);
239 case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET:
240 encode_value (var->index, p, &p);
241 encode_value (var->offset, p, &p);
244 g_assert_not_reached ();
250 mono_debug_serialize_debug_info (MonoCompile *cfg,
251 guint8 **out_buf, guint32 *buf_len)
253 MiniDebugMethodInfo *info;
254 MonoDebugMethodJitInfo *jit;
255 guint32 size, prev_offset, prev_native_offset;
260 info = (MiniDebugMethodInfo *) cfg->debug_info;
261 if (!info || !info->jit) {
267 size = ((jit->num_params + jit->num_locals + 1) * 10) + (jit->line_numbers->len * 10) + 64;
268 p = buf = g_malloc (size);
269 encode_value (jit->epilogue_begin, p, &p);
270 encode_value (jit->prologue_end, p, &p);
271 encode_value (jit->code_size, p, &p);
273 for (i = 0; i < jit->num_params; ++i)
274 serialize_variable (&jit->params [i], p, &p);
276 if (cfg->method->signature->hasthis)
277 serialize_variable (jit->this_var, p, &p);
279 for (i = 0; i < jit->num_locals; i++)
280 serialize_variable (&jit->locals [i], p, &p);
282 encode_value (jit->line_numbers->len, p, &p);
285 prev_native_offset = 0;
286 for (i = 0; i < jit->line_numbers->len; ++i) {
287 MonoDebugLineNumberEntry *lne = &g_array_index (jit->line_numbers,
288 MonoDebugLineNumberEntry,
290 encode_value (lne->offset - prev_offset, p, &p);
291 encode_value (lne->address - prev_native_offset, p, &p);
292 prev_offset = lne->offset;
293 prev_native_offset = lne->address;
296 g_assert (p - buf < size);
303 deserialize_variable (MonoDebugVarInfo *var, char *p, char **endbuf)
307 var->index = decode_value (p, &p);
309 flags = var->index & MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
312 case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER:
314 case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET:
315 var->offset = decode_value (p, &p);
318 g_assert_not_reached ();
323 static MonoDebugMethodJitInfo *
324 deserialize_debug_info (MonoMethod *method,
326 guint8 *buf, guint32 buf_len)
328 MonoMethodHeader *header;
329 MonoDebugMethodJitInfo *jit;
330 guint32 offset, native_offset, prev_offset, prev_native_offset, len;
334 g_assert (((MonoMethodNormal*)method)->header);
335 header = ((MonoMethodNormal*)method)->header;
337 jit = g_new0 (MonoDebugMethodJitInfo, 1);
338 jit->code_start = code_start;
339 jit->line_numbers = g_array_new (FALSE, TRUE, sizeof (MonoDebugLineNumberEntry));
340 jit->num_locals = header->num_locals;
341 jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
342 jit->num_params = method->signature->param_count;
343 jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
346 jit->epilogue_begin = decode_value (p, &p);
347 jit->prologue_end = decode_value (p, &p);
348 jit->code_size = decode_value (p, &p);
350 for (i = 0; i < jit->num_params; ++i)
351 deserialize_variable (&jit->params [i], p, &p);
353 if (method->signature->hasthis) {
354 jit->this_var = g_new0 (MonoDebugVarInfo, 1);
355 deserialize_variable (jit->this_var, p, &p);
358 for (i = 0; i < jit->num_locals; i++)
359 deserialize_variable (&jit->locals [i], p, &p);
361 len = decode_value (p, &p);
364 prev_native_offset = 0;
365 for (i = 0; i < len; ++i) {
366 offset = prev_offset + decode_value (p, &p);
367 native_offset = prev_native_offset + decode_value (p, &p);
368 record_line_number (jit, native_offset, offset);
369 prev_offset = offset;
370 prev_native_offset = native_offset;
377 mono_debug_add_aot_method (MonoDomain *domain,
378 MonoMethod *method, guint8 *code_start,
379 guint8 *debug_info, guint32 debug_info_len)
381 MonoDebugMethodJitInfo *jit;
383 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
386 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
387 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
388 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
389 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
390 (method->wrapper_type != MONO_WRAPPER_NONE))
393 if (debug_info_len == 0)
396 jit = deserialize_debug_info (method, code_start,
400 mono_debug_add_method (method, jit, domain);
404 mono_init_debugger (const char *file, const char *opt_flags)
410 g_set_prgname (file);
412 opt = mono_parse_default_optimizations (opt_flags);
413 opt |= MONO_OPT_SHARED;
415 mono_set_defaults (0, opt);
417 domain = mono_jit_init (file);
419 mono_config_parse (NULL);
421 error = mono_verify_corlib ();
423 fprintf (stderr, "Corlib not in sync with this runtime: %s\n", error);