2003-10-09 Dick Porter <dick@ximian.com>
[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 <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... */
16 #include "config.h"
17 #include <mono/metadata/mono-debug-debugger.h>
18
19 static void
20 record_line_number (MonoDebugMethodJitInfo *jit, guint32 address, guint32 offset)
21 {
22         MonoDebugLineNumberEntry *lne = g_new0 (MonoDebugLineNumberEntry, 1);
23
24         lne->address = address;
25         lne->offset = offset;
26
27         g_array_append_val (jit->line_numbers, *lne);
28 }
29
30 typedef struct
31 {
32         MonoDebugMethodJitInfo *jit;
33         guint32 has_line_numbers;
34         guint32 breakpoint_id;
35 } MiniDebugMethodInfo;
36
37 void
38 mono_debug_init_method (MonoCompile *cfg, MonoBasicBlock *start_block, guint32 breakpoint_id)
39 {
40         MonoMethod *method = cfg->method;
41         MiniDebugMethodInfo *info;
42
43         if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
44                 return;
45
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))
51                 return;
52
53         info = g_new0 (MiniDebugMethodInfo, 1);
54         info->breakpoint_id = breakpoint_id;
55
56         cfg->debug_info = info;
57 }
58
59 void
60 mono_debug_open_method (MonoCompile *cfg)
61 {
62         MiniDebugMethodInfo *info;
63         MonoDebugMethodJitInfo *jit;
64         MonoMethodHeader *header;
65
66         info = (MiniDebugMethodInfo *) cfg->debug_info;
67         if (!info)
68                 return;
69
70         mono_class_init (cfg->method->klass);
71
72         g_assert (((MonoMethodNormal*)cfg->method)->header);
73         header = ((MonoMethodNormal*)cfg->method)->header;
74
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);
79 }
80
81 static void
82 write_variable (MonoInst *inst, MonoDebugVarInfo *var)
83 {
84         if (inst->opcode == OP_REGVAR)
85                 var->index = inst->dreg | MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER;
86         else {
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;
90         }
91 }
92
93 void
94 mono_debug_close_method (MonoCompile *cfg)
95 {
96         MiniDebugMethodInfo *info;
97         MonoDebugMethodJitInfo *jit;
98         MonoMethodHeader *header;
99         MonoMethod *method;
100         int i;
101
102         info = (MiniDebugMethodInfo *) cfg->debug_info;
103         if (!info || !info->jit)
104                 return;
105
106         method = cfg->method;
107         header = ((MonoMethodNormal*)method)->header;
108
109         jit = info->jit;
110         jit->code_start = cfg->native_code;
111         jit->epilogue_begin = cfg->epilog_begin;
112         jit->code_size = cfg->code_len;
113
114         record_line_number (jit, jit->epilogue_begin, header->code_size);
115
116         jit->num_params = method->signature->param_count;
117         jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
118
119         for (i = 0; i < jit->num_locals; i++)
120                 write_variable (cfg->varinfo [cfg->locals_start + i], &jit->locals [i]);
121
122         if (method->signature->hasthis) {
123                 jit->this_var = g_new0 (MonoDebugVarInfo, 1);
124                 write_variable (cfg->varinfo [0], jit->this_var);
125         }
126
127         for (i = 0; i < jit->num_params; i++)
128                 write_variable (cfg->varinfo [i + method->signature->hasthis], &jit->params [i]);
129
130         mono_debug_add_method (method, jit, cfg->domain);
131
132         if (info->breakpoint_id)
133                 mono_debugger_breakpoint_callback (method, info->breakpoint_id);
134 }
135
136 void
137 mono_debug_record_line_number (MonoCompile *cfg, MonoInst *ins, guint32 address)
138 {
139         MiniDebugMethodInfo *info;
140         MonoMethodHeader *header;
141         guint32 offset;
142
143         info = (MiniDebugMethodInfo *) cfg->debug_info;
144         if (!info || !info->jit || !ins->cil_code)
145                 return;
146
147         g_assert (((MonoMethodNormal*)cfg->method)->header);
148         header = ((MonoMethodNormal*)cfg->method)->header;
149
150         if ((ins->cil_code < header->code) ||
151             (ins->cil_code > header->code + header->code_size))
152                 return;
153
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;
158         }
159
160         record_line_number (info->jit, address, offset);
161 }
162
163 MonoDomain *
164 mono_init_debugger (const char *file, const char *opt_flags)
165 {
166         MonoDomain *domain;
167         const char *error;
168         int opt;
169
170         g_set_prgname (file);
171
172         opt = mono_parse_default_optimizations (opt_flags);
173         opt |= MONO_OPT_SHARED;
174
175         mono_set_defaults (0, opt);
176
177         domain = mono_jit_init (file);
178
179         mono_config_parse (NULL);
180
181         error = mono_verify_corlib ();
182         if (error) {
183                 fprintf (stderr, "Corlib not in sync with this runtime: %s\n", error);
184                 exit (1);
185         }
186
187         return domain;
188 }