Fix problems with overlong directory names: phase #1
[mono.git] / mono / mini / debug-mini.c
1 /*
2  * debug-mini.c: Mini-specific debugging stuff.
3  *
4  * Author:
5  *   Martin Baulig (martin@ximian.com)
6  *
7  * (C) 2003 Ximian, Inc.
8  */
9
10 #include "mini.h"
11 #include "jit.h"
12 #include "config.h"
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/mono-debug-debugger.h>
18
19 #ifdef HAVE_VALGRIND_H
20 #include <valgrind/valgrind.h>
21 #endif
22
23 typedef struct
24 {
25         MonoDebugMethodJitInfo *jit;
26         GArray *line_numbers;
27         guint32 has_line_numbers;
28         guint32 breakpoint_id;
29 } MiniDebugMethodInfo;
30
31 static inline void
32 record_line_number (MiniDebugMethodInfo *info, guint32 address, guint32 offset)
33 {
34         MonoDebugLineNumberEntry lne;
35
36         lne.native_offset = address;
37         lne.il_offset = offset;
38
39         g_array_append_val (info->line_numbers, lne);
40 }
41
42 void
43 mono_debug_init_method (MonoCompile *cfg, MonoBasicBlock *start_block, guint32 breakpoint_id)
44 {
45         MiniDebugMethodInfo *info;
46
47         if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
48                 return;
49
50         info = g_new0 (MiniDebugMethodInfo, 1);
51         info->breakpoint_id = breakpoint_id;
52
53         cfg->debug_info = info;
54 }
55
56 void
57 mono_debug_open_method (MonoCompile *cfg)
58 {
59         MiniDebugMethodInfo *info;
60         MonoDebugMethodJitInfo *jit;
61         MonoMethodHeader *header;
62
63         info = (MiniDebugMethodInfo *) cfg->debug_info;
64         if (!info)
65                 return;
66
67         mono_class_init (cfg->method->klass);
68
69         header = mono_method_get_header (cfg->method);
70         g_assert (header);
71         
72         info->jit = jit = g_new0 (MonoDebugMethodJitInfo, 1);
73         info->line_numbers = g_array_new (FALSE, TRUE, sizeof (MonoDebugLineNumberEntry));
74         jit->num_locals = header->num_locals;
75         jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
76 }
77
78 static void
79 write_variable (MonoInst *inst, MonoDebugVarInfo *var)
80 {
81         if (inst->opcode == OP_REGVAR)
82                 var->index = inst->dreg | MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER;
83         else {
84                 /* the debug interface needs fixing to allow 0(%base) address */
85                 var->index = inst->inst_basereg | MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET;
86                 var->offset = inst->inst_offset;
87         }
88 }
89
90 /*
91  * mono_debug_add_vg_method:
92  *
93  *  Register symbol information for the method with valgrind
94  */
95 static void 
96 mono_debug_add_vg_method (MonoMethod *method, MonoDebugMethodJitInfo *jit)
97 {
98 #ifdef VALGRIND_ADD_LINE_INFO
99         MonoMethodHeader *header;
100         MonoDebugMethodInfo *minfo;
101         int i;
102         char *filename = NULL;
103         guint32 address, line_number;
104         const char *full_name;
105         guint32 *addresses;
106         guint32 *lines;
107
108         if (!RUNNING_ON_VALGRIND)
109                 return;
110
111         header = mono_method_get_header (method);
112
113         full_name = mono_method_full_name (method, TRUE);
114
115         addresses = g_new0 (guint32, header->code_size + 1);
116         lines = g_new0 (guint32, header->code_size + 1);
117
118         /* 
119          * Very simple code to convert the addr->offset mappings that mono has
120          * into [addr-addr] ->line number mappings.
121          */
122
123         minfo = mono_debug_lookup_method (method);
124         if (minfo) {
125                 /* Create offset->line number mapping */
126                 for (i = 0; i < header->code_size; ++i) {
127                         MonoDebugSourceLocation *location;
128
129                         location = mono_debug_symfile_lookup_location (minfo, i);
130                         if (!location)
131                                 continue;
132
133                         lines [i] = location.row;
134                         if (!filename)
135                                 filename = location.source_file;
136
137                         mono_debug_free_source_location (location);
138                 }
139         }
140
141         /* Create address->offset mapping */
142         for (i = 0; i < jit->num_line_numbers; ++i) {
143                 MonoDebugLineNumberEntry *lne = jit->line_numbers [i];
144
145                 g_assert (lne->offset <= header->code_size);
146
147                 if ((addresses [lne->offset] == 0) || (lne->address < addresses [lne->offset]))
148                         addresses [lne->offset] = lne->address;
149         }
150         /* Fill out missing addresses */
151         address = 0;
152         for (i = 0; i < header->code_size; ++i) {
153                 if (addresses [i] == 0)
154                         addresses [i] = address;
155                 else
156                         address = addresses [i];
157         }
158         
159         address = 0;
160         line_number = 0;
161         i = 0;
162         while (i < header->code_size) {
163                 if (lines [i] == line_number)
164                         i ++;
165                 else {
166                         if (line_number > 0) {
167                                 //g_assert (addresses [i] - 1 >= address);
168                                 
169                                 if (addresses [i] - 1 >= address) {
170                                         VALGRIND_ADD_LINE_INFO (jit->code_start + address, jit->code_start + addresses [i] - 1, filename, line_number);
171                                         //printf ("[%d-%d] -> %d.\n", address, addresses [i] - 1, line_number);
172                                 }
173                         }
174                         address = addresses [i];
175                         line_number = lines [i];
176                 }
177         }
178
179         if (line_number > 0) {
180                 VALGRIND_ADD_LINE_INFO (jit->code_start + address, jit->code_start + jit->code_size - 1, filename, line_number);
181                 //printf ("[%d-%d] -> %d.\n", address, jit->code_size - 1, line_number);
182         }
183
184         VALGRIND_ADD_SYMBOL (jit->code_start, jit->code_size, full_name);
185
186         g_free (addresses);
187         g_free (lines);
188 #endif /* VALGRIND_ADD_LINE_INFO */
189 }
190
191 void
192 mono_debug_close_method (MonoCompile *cfg)
193 {
194         MiniDebugMethodInfo *info;
195         MonoDebugMethodJitInfo *jit;
196         MonoMethodHeader *header;
197         MonoMethodSignature *sig;
198         MonoMethod *method;
199         int i;
200
201         info = (MiniDebugMethodInfo *) cfg->debug_info;
202         if (!info || !info->jit) {
203                 if (info)
204                         g_free (info);
205                 return;
206         }
207
208         method = cfg->method;
209         header = mono_method_get_header (method);
210         sig = mono_method_signature (method);
211
212         jit = info->jit;
213         jit->code_start = cfg->native_code;
214         jit->epilogue_begin = cfg->epilog_begin;
215         jit->code_size = cfg->code_len;
216
217         record_line_number (info, jit->epilogue_begin, header->code_size);
218
219         jit->num_params = sig->param_count;
220         jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
221
222         for (i = 0; i < jit->num_locals; i++)
223                 write_variable (cfg->varinfo [cfg->locals_start + i], &jit->locals [i]);
224
225         if (sig->hasthis) {
226                 jit->this_var = g_new0 (MonoDebugVarInfo, 1);
227                 write_variable (cfg->varinfo [0], jit->this_var);
228         }
229
230         for (i = 0; i < jit->num_params; i++)
231                 write_variable (cfg->varinfo [i + sig->hasthis], &jit->params [i]);
232
233         jit->num_line_numbers = info->line_numbers->len;
234         jit->line_numbers = g_new0 (MonoDebugLineNumberEntry, jit->num_line_numbers);
235
236         for (i = 0; i < jit->num_line_numbers; i++)
237                 jit->line_numbers [i] = g_array_index (info->line_numbers, MonoDebugLineNumberEntry, i);
238
239         mono_debug_add_method (method, jit, cfg->domain);
240
241         mono_debug_add_vg_method (method, jit);
242
243         if (info->breakpoint_id)
244                 mono_debugger_breakpoint_callback (method, info->breakpoint_id);
245
246         mono_debug_free_method_jit_info (jit);
247         g_array_free (info->line_numbers, TRUE);
248         g_free (info);
249 }
250
251 void
252 mono_debug_record_line_number (MonoCompile *cfg, MonoInst *ins, guint32 address)
253 {
254         MiniDebugMethodInfo *info;
255         MonoMethodHeader *header;
256         guint32 offset;
257
258         info = (MiniDebugMethodInfo *) cfg->debug_info;
259         if (!info || !info->jit || !ins->cil_code)
260                 return;
261
262         header = mono_method_get_header (cfg->method);
263         g_assert (header);
264
265         if ((ins->cil_code < header->code) ||
266             (ins->cil_code > header->code + header->code_size))
267                 return;
268
269         offset = ins->cil_code - header->code;
270         if (!info->has_line_numbers) {
271                 info->jit->prologue_end = address;
272                 info->has_line_numbers = TRUE;
273         }
274
275         record_line_number (info, address, offset);
276 }
277
278 void
279 mono_debug_open_block (MonoCompile *cfg, MonoBasicBlock *bb, guint32 address)
280 {
281         MiniDebugMethodInfo *info;
282         MonoMethodHeader *header;
283         guint32 offset;
284
285         info = (MiniDebugMethodInfo *) cfg->debug_info;
286         if (!info || !info->jit || !bb->cil_code)
287                 return;
288
289         header = mono_method_get_header (cfg->method);
290         g_assert (header);
291
292         if ((bb->cil_code < header->code) ||
293             (bb->cil_code > header->code + header->code_size))
294                 return;
295
296         offset = bb->cil_code - header->code;
297         if (!info->has_line_numbers) {
298                 info->jit->prologue_end = address;
299                 info->has_line_numbers = TRUE;
300         }
301
302         record_line_number (info, address, offset);
303 }
304
305 static inline void
306 encode_value (gint32 value, guint8 *buf, guint8 **endbuf)
307 {
308         guint8 *p = buf;
309
310         //printf ("ENCODE: %d 0x%x.\n", value, value);
311
312         /* 
313          * Same encoding as the one used in the metadata, extended to handle values
314          * greater than 0x1fffffff.
315          */
316         if ((value >= 0) && (value <= 127))
317                 *p++ = value;
318         else if ((value >= 0) && (value <= 16383)) {
319                 p [0] = 0x80 | (value >> 8);
320                 p [1] = value & 0xff;
321                 p += 2;
322         } else if ((value >= 0) && (value <= 0x1fffffff)) {
323                 p [0] = (value >> 24) | 0xc0;
324                 p [1] = (value >> 16) & 0xff;
325                 p [2] = (value >> 8) & 0xff;
326                 p [3] = value & 0xff;
327                 p += 4;
328         }
329         else {
330                 p [0] = 0xff;
331                 p [1] = (value >> 24) & 0xff;
332                 p [2] = (value >> 16) & 0xff;
333                 p [3] = (value >> 8) & 0xff;
334                 p [4] = value & 0xff;
335                 p += 5;
336         }
337         if (endbuf)
338                 *endbuf = p;
339 }
340
341 static inline gint32
342 decode_value (guint8 *ptr, guint8 **rptr)
343 {
344         guint8 b = *ptr;
345         gint32 len;
346         
347         if ((b & 0x80) == 0){
348                 len = b;
349                 ++ptr;
350         } else if ((b & 0x40) == 0){
351                 len = ((b & 0x3f) << 8 | ptr [1]);
352                 ptr += 2;
353         } else if (b != 0xff) {
354                 len = ((b & 0x1f) << 24) |
355                         (ptr [1] << 16) |
356                         (ptr [2] << 8) |
357                         ptr [3];
358                 ptr += 4;
359         }
360         else {
361                 len = (ptr [1] << 24) | (ptr [2] << 16) | (ptr [3] << 8) | ptr [4];
362                 ptr += 5;
363         }
364         if (rptr)
365                 *rptr = ptr;
366
367         //printf ("DECODE: %d.\n", len);
368         return len;
369 }
370
371 static void
372 serialize_variable (MonoDebugVarInfo *var, guint8 *p, guint8 **endbuf)
373 {
374         guint32 flags = var->index & MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
375
376         switch (flags) {
377         case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER:
378                 encode_value (var->index, p, &p);
379                 break;
380         case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET:
381                 encode_value (var->index, p, &p);
382                 encode_value (var->offset, p, &p);
383                 break;
384         default:
385                 g_assert_not_reached ();
386         }
387         *endbuf = p;
388 }
389
390 void
391 mono_debug_serialize_debug_info (MonoCompile *cfg, guint8 **out_buf, guint32 *buf_len)
392 {
393         MiniDebugMethodInfo *info;
394         MonoDebugMethodJitInfo *jit;
395         guint32 size, prev_offset, prev_native_offset;
396         guint8 *buf, *p;
397         int i;
398
399         info = (MiniDebugMethodInfo *) cfg->debug_info;
400         if (!info || !info->jit) {
401                 *buf_len = 0;
402                 return;
403         }
404         jit = info->jit;
405
406         size = ((jit->num_params + jit->num_locals + 1) * 10) + (jit->num_line_numbers * 10) + 64;
407         p = buf = g_malloc (size);
408         encode_value (jit->epilogue_begin, p, &p);
409         encode_value (jit->prologue_end, p, &p);
410         encode_value (jit->code_size, p, &p);
411
412         for (i = 0; i < jit->num_params; ++i)
413                 serialize_variable (&jit->params [i], p, &p);
414
415         if (mono_method_signature (cfg->method)->hasthis)
416                 serialize_variable (jit->this_var, p, &p);
417
418         for (i = 0; i < jit->num_locals; i++)
419                 serialize_variable (&jit->locals [i], p, &p);
420
421         encode_value (jit->num_line_numbers, p, &p);
422
423         prev_offset = 0;
424         prev_native_offset = 0;
425         for (i = 0; i < jit->num_line_numbers; ++i) {
426                 /* Sometimes, the offset values are not in increasing order */
427                 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
428                 encode_value (lne->il_offset - prev_offset, p, &p);
429                 encode_value (lne->native_offset - prev_native_offset, p, &p);
430                 prev_offset = lne->il_offset;
431                 prev_native_offset = lne->native_offset;
432         }
433
434         g_assert (p - buf < size);
435
436         *out_buf = buf;
437         *buf_len = p - buf;
438 }
439
440 static void
441 deserialize_variable (MonoDebugVarInfo *var, guint8 *p, guint8 **endbuf)
442 {
443         guint32 flags;
444
445         var->index = decode_value (p, &p);
446
447         flags = var->index & MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
448
449         switch (flags) {
450         case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER:
451                 break;
452         case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET:
453                 var->offset = decode_value (p, &p);
454                 break;
455         default:
456                 g_assert_not_reached ();
457         }
458         *endbuf = p;
459 }
460
461 static MonoDebugMethodJitInfo *
462 deserialize_debug_info (MonoMethod *method, guint8 *code_start, guint8 *buf, guint32 buf_len)
463 {
464         MonoMethodHeader *header;
465         gint32 offset, native_offset, prev_offset, prev_native_offset;
466         MonoDebugMethodJitInfo *jit;
467         guint8 *p;
468         int i;
469
470         header = mono_method_get_header (method);
471         g_assert (header);
472
473         jit = g_new0 (MonoDebugMethodJitInfo, 1);
474         jit->code_start = code_start;
475         jit->num_locals = header->num_locals;
476         jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
477         jit->num_params = mono_method_signature (method)->param_count;
478         jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
479
480         p = buf;
481         jit->epilogue_begin = decode_value (p, &p);
482         jit->prologue_end = decode_value (p, &p);
483         jit->code_size = decode_value (p, &p);
484
485         for (i = 0; i < jit->num_params; ++i)
486                 deserialize_variable (&jit->params [i], p, &p);
487
488         if (mono_method_signature (method)->hasthis) {
489                 jit->this_var = g_new0 (MonoDebugVarInfo, 1);
490                 deserialize_variable (jit->this_var, p, &p);
491         }
492
493         for (i = 0; i < jit->num_locals; i++)
494                 deserialize_variable (&jit->locals [i], p, &p);
495
496         jit->num_line_numbers = decode_value (p, &p);
497         jit->line_numbers = g_new0 (MonoDebugLineNumberEntry, jit->num_line_numbers);
498
499         prev_offset = 0;
500         prev_native_offset = 0;
501         for (i = 0; i < jit->num_line_numbers; ++i) {
502                 MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];
503
504                 offset = prev_offset + decode_value (p, &p);
505                 native_offset = prev_native_offset + decode_value (p, &p);
506
507                 lne->native_offset = native_offset;
508                 lne->il_offset = offset;
509
510                 prev_offset = offset;
511                 prev_native_offset = native_offset;
512         }
513
514         return jit;
515 }
516
517 void
518 mono_debug_add_aot_method (MonoDomain *domain, MonoMethod *method, guint8 *code_start, 
519                            guint8 *debug_info, guint32 debug_info_len)
520 {
521         MonoDebugMethodJitInfo *jit;
522
523         if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
524                 return;
525
526         if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
527             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
528             (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
529             (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
530             (method->wrapper_type != MONO_WRAPPER_NONE))
531                 return;
532
533         if (debug_info_len == 0)
534                 return;
535
536         jit = deserialize_debug_info (method, code_start, debug_info, debug_info_len);
537
538 #if 0
539         jit = mono_debug_read_method ((MonoDebugMethodAddress *) debug_info);
540         jit->code_start = code_start;
541         jit->wrapper_addr = NULL;
542 #endif
543
544         mono_debug_add_method (method, jit, domain);
545
546         mono_debug_add_vg_method (method, jit);
547
548         mono_debug_free_method_jit_info (jit);
549 }
550
551 void
552 mono_debug_add_icall_wrapper (MonoMethod *method, MonoJitICallInfo* callinfo)
553 {
554         if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
555                 return;
556
557         // mono_debug_add_wrapper (method, callinfo->wrapper, callinfo->func);
558 }
559
560 static void
561 print_var_info (MonoDebugVarInfo *info, int idx, const char *name, const char *type)
562 {
563         switch (info->index & MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS) {
564         case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER:
565                 g_print ("%s %s (%d) in register %s\n", type, name, idx, mono_arch_regname (info->index & (~MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS)));
566                 break;
567         case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET:
568                 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);
569                 break;
570         case MONO_DEBUG_VAR_ADDRESS_MODE_TWO_REGISTERS:
571         default:
572                 g_assert_not_reached ();
573         }
574 }
575
576 /**
577  * mono_debug_print_locals:
578  *
579  * Prints to stdout the information about the local variables in
580  * a method (if @only_arguments is false) or about the arguments.
581  * The information includes the storage info (where the variable 
582  * lives, in a register or in memory).
583  * The method is found by looking up what method has been emitted at
584  * the instruction address @ip.
585  * This is for use inside a debugger.
586  */
587 void
588 mono_debug_print_vars (gpointer ip, gboolean only_arguments)
589 {
590         MonoDomain *domain = mono_domain_get ();
591         MonoJitInfo *ji = mono_jit_info_table_find (domain, ip);
592         MonoDebugMethodInfo *minfo;
593         MonoDebugMethodJitInfo *jit;
594         int i;
595
596         if (!ji)
597                 return;
598
599         minfo = mono_debug_lookup_method (mono_jit_info_get_method (ji));
600         if (!minfo)
601                 return;
602
603         jit = mono_debug_find_method (minfo, domain);
604         if (!jit)
605                 return;
606         if (only_arguments) {
607                 char **names;
608                 names = g_new (char *, jit->num_params);
609                 mono_method_get_param_names (mono_jit_info_get_method (ji), (const char **) names);
610                 if (jit->this_var)
611                         print_var_info (jit->this_var, 0, "this", "Arg");
612                 for (i = 0; i < jit->num_params; ++i) {
613                         print_var_info (&jit->params [i], i, names [i]? names [i]: "unknown name", "Arg");
614                 }
615                 g_free (names);
616         } else {
617                 for (i = 0; i < jit->num_locals; ++i) {
618                         print_var_info (&jit->locals [i], i, "", "Local");
619                 }
620         }
621 }
622