2004-06-08 Martin Baulig <martin@ximian.com>
[mono.git] / mono / jit / debug-jit.c
1 #include <config.h>
2 #include <mono/metadata/mono-debug.h>
3 #include <mono/metadata/mono-debug-debugger.h>
4 #include <mono/jit/debug-jit.h>
5 #include "codegen.h"
6
7 /*
8  * This method is only called when running in the Mono Debugger.
9  */
10 gpointer
11 mono_debugger_create_notification_function (gpointer *notification_address)
12 {
13         guint8 *ptr, *buf;
14
15         ptr = buf = g_malloc0 (16);
16         x86_breakpoint (buf);
17         if (notification_address)
18                 *notification_address = buf;
19         x86_ret (buf);
20
21         return ptr;
22 }
23
24 static void
25 record_line_number (MonoDebugMethodJitInfo *jit, guint32 address, guint32 offset)
26 {
27         MonoDebugLineNumberEntry *lne = g_new0 (MonoDebugLineNumberEntry, 1);
28
29         lne->address = address;
30         lne->offset = offset;
31
32         g_array_append_val (jit->line_numbers, *lne);
33 }
34
35 static void
36 debug_update_il_offsets (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoFlowGraph* cfg)
37 {
38         MonoMethodHeader *header;
39         guint32 address, offset;
40         int i;
41
42         jit->line_numbers = g_array_new (FALSE, TRUE, sizeof (MonoDebugLineNumberEntry));
43
44         address = jit->prologue_end;
45         offset = 0;
46
47         g_assert (((MonoMethodNormal*)method)->header);
48         header = ((MonoMethodNormal*)method)->header;
49
50         record_line_number (jit, address, offset);
51
52         /* start lines of basic blocks */
53         for (i = 0; i < cfg->block_count; ++i) {
54                 int j;
55
56                 for (j = 0; cfg->bblocks [i].forest && (j < cfg->bblocks [i].forest->len); ++j) {
57                         MBTree *t = (MBTree *) g_ptr_array_index (cfg->bblocks [i].forest, j);
58
59                         if ((t->cli_addr == -1) || (t->cli_addr == offset) || (t->addr == address))
60                                 continue;
61
62                         offset = t->cli_addr;
63                         address = t->addr;
64
65                         record_line_number (jit, address, offset);
66                 }
67         }
68
69         record_line_number (jit, jit->epilogue_begin, header->code_size);
70 }
71
72 static gint32
73 il_offset_from_position (MonoFlowGraph *cfg, MonoPosition *pos)
74 {
75         MonoBBlock *bblock;
76         MBTree *tree;
77
78         if (pos->abs_pos == 0)
79                 return -1;
80
81         if (pos->pos.bid >= cfg->block_count)
82                 return -1;
83
84         bblock = &cfg->bblocks [pos->pos.bid];
85         if (pos->pos.tid >= bblock->forest->len)
86                 return -1;
87
88         tree = (MBTree *) g_ptr_array_index (bblock->forest, pos->pos.tid);
89
90         return tree->cli_addr;
91 }
92
93 static gint32
94 address_from_il_offset (MonoDebugMethodJitInfo *jit, guint32 il_offset)
95 {
96         int i;
97
98         for (i = jit->line_numbers->len - 1; i >= 0; i--) {
99                 MonoDebugLineNumberEntry lne = g_array_index (
100                         jit->line_numbers, MonoDebugLineNumberEntry, i);
101
102                 if (lne.offset <= il_offset)
103                         return lne.address;
104         }
105
106         return -1;
107 }
108
109 void
110 mono_debug_jit_add_method (MonoFlowGraph *cfg)
111 {
112         MonoMethod *method = cfg->method;
113         MonoClass *klass = method->klass;
114         MonoDebugMethodJitInfo *jit;
115         int i;
116
117         mono_class_init (klass);
118
119         if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
120             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
121             (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
122             (method->flags & METHOD_ATTRIBUTE_ABSTRACT))
123                 return;
124
125         jit = g_new0 (MonoDebugMethodJitInfo, 1);
126         jit->code_start = cfg->start;
127         jit->code_size = cfg->epilogue_end;
128         jit->prologue_end = cfg->prologue_end;
129         jit->epilogue_begin = cfg->epilog;
130         jit->num_params = method->signature->param_count;
131         jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
132
133         if (method->signature->hasthis) {
134                 MonoVarInfo *ptr = ((MonoVarInfo *) cfg->varinfo->data) + cfg->args_start_index;
135
136                 jit->this_var = g_new0 (MonoDebugVarInfo, 1);
137                 jit->this_var->offset = ptr->offset;
138                 jit->this_var->size = ptr->size;
139         }
140
141         for (i = 0; i < jit->num_params; i++) {
142                 MonoVarInfo *ptr = ((MonoVarInfo *) cfg->varinfo->data) + cfg->args_start_index +
143                         method->signature->hasthis;
144
145                 jit->params [i].offset = ptr [i].offset;
146                 jit->params [i].size = ptr [i].size;
147         }
148
149         debug_update_il_offsets (method, jit, cfg);
150
151         if (!method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
152                 MonoMethodHeader *header = ((MonoMethodNormal*)method)->header;
153                 MonoVarInfo *ptr = ((MonoVarInfo *) cfg->varinfo->data) + cfg->locals_start_index;
154                 MonoDebugVarInfo *locals;
155
156                 locals = g_new0 (MonoDebugVarInfo, header->num_locals);
157                 for (i = 0; i < header->num_locals; i++) {
158                         gint32 begin_offset, end_offset;
159                         gint32 begin_scope, end_scope;
160
161                         if (ptr [i].reg >= 0) {
162                                 locals [i].index = ptr [i].reg | MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER;
163                                 locals [i].offset = 0;
164                         } else
165                                 locals [i].offset = ptr [i].offset;
166
167                         locals [i].size = ptr [i].size;
168
169                         begin_offset = il_offset_from_position (cfg, &ptr [i].range.first_use);
170                         end_offset = il_offset_from_position (cfg, &ptr [i].range.last_use);
171                         if (end_offset >= 0)
172                                 end_offset++;
173
174                         if (begin_offset >= 0)
175                                 begin_scope = address_from_il_offset (jit, begin_offset);
176                         else
177                                 begin_scope = -1;
178                         if (end_offset >= 0)
179                                 end_scope = address_from_il_offset (jit, end_offset);
180                         else
181                                 end_scope = -1;
182
183                         if (begin_scope > 0)
184                                 locals [i].begin_scope = begin_scope;
185                         else
186                                 locals [i].begin_scope = jit->prologue_end;
187                         if (end_scope > 0)
188                                 locals [i].end_scope = end_scope;
189                         else
190                                 locals [i].end_scope = jit->epilogue_begin;
191                 }
192
193                 jit->num_locals = header->num_locals;
194                 jit->locals = locals;
195         }
196
197         mono_debug_add_method (method, jit, cfg->domain);
198 }