3 #include <mono/metadata/class.h>
4 #include <mono/metadata/tabledefs.h>
5 #include <mono/metadata/tokentype.h>
6 #include <mono/jit/codegen.h>
17 struct _MonoDebugHandle {
31 * Note: same order of MonoTypeEnum.
37 {"Boolean", ";0;255;"},
38 {"Char", ";0;65535;"},
39 {"SByte", ";-128;127;"},
41 {"Int16", ";-32768;32767;"},
42 {"UInt16", ";0;65535;"},
43 {"Int32", ";0020000000000;0017777777777;"},
44 {"UInt32", ";0000000000000;0037777777777;"},
45 {"Int64", ";01000000000000000000000;0777777777777777777777;"},
46 {"UInt64", ";0000000000000;01777777777777777777777;"},
47 {"Single", "r(0,8);4;0;"},
48 {"Double", "r(0,8);8;0;"},
49 {"String", "(0,41)=*(0,42)=xsMonoString:"}, /*string*/
53 {"Class", "(0,44)=*(0,45)=xsMonoObject:"}, /*class*/
55 {"Array", }, /*array*/
56 {"", }, /*typedbyref*/
59 {"IntPtr", ";0020000000000;0017777777777;"},
60 {"UIntPtr", ";0000000000000;0037777777777;"},
62 {"FnPtr", "*(0,1)"}, /*fnptr*/
63 {"Object", "(0,47)=*(0,48)=xsMonoObject:"}, /*object*/
64 {"SzArray", "(0,50)=*(0,51))=xsMonoArray:"}, /*szarray*/
69 output_std_stuff (AssemblyDebugInfo* debug)
72 for (i = 0; base_types [i].name; ++i) {
73 if (! base_types [i].spec)
75 fprintf (debug->f, ".stabs \"%s:t(0,%d)=", base_types [i].name, i);
76 if (base_types [i].spec [0] == ';') {
77 fprintf (debug->f, "r(0,%d)%s\"", i, base_types [i].spec);
79 fprintf (debug->f, "%s\"", base_types [i].spec);
81 fprintf (debug->f, ",128,0,0,0\n");
86 mono_debug_open_file (char *filename)
88 MonoDebugHandle *debug;
90 debug = g_new0 (MonoDebugHandle, 1);
91 debug->name = g_strdup (filename);
96 debug_load_method_lines (AssemblyDebugInfo* info)
101 char *name = g_strdup_printf ("%s.il", info->name);
103 /* use an env var with directories for searching. */
104 if (!(f = fopen (name, "r"))) {
105 g_warning ("cannot open IL assembly file %s", name);
111 while (fgets (buf, sizeof (buf), f)) {
113 if (sscanf (buf, " // method line %d", &mnum) && mnum < info->nmethods) {
114 while (fgets (buf, sizeof (buf), f)) {
116 if (strstr (buf, "}"))
117 break; /* internalcall or runtime method */
118 if (strstr (buf, "IL_0000:"))
121 /* g_print ("method %d found at %d\n", mnum, i); */
122 info->mlines [mnum] = i;
128 static AssemblyDebugInfo*
129 mono_debug_open_ass (MonoDebugHandle* handle, MonoImage *image)
132 AssemblyDebugInfo* info;
134 for (tmp = handle->info; tmp; tmp = tmp->next) {
135 info = (AssemblyDebugInfo*)tmp->data;
136 if (strcmp (info->name, image->assembly_name) == 0)
139 info = g_new0 (AssemblyDebugInfo, 1);
140 info->filename = g_strdup_printf ("%s-stabs.s", image->assembly_name);
141 if (!(info->f = fopen (info->filename, "w"))) {
142 g_free (info->filename);
146 info->name = g_strdup (image->assembly_name);
148 fprintf (info->f, ".stabs \"%s.il\",100,0,0,0\n", image->assembly_name);
149 output_std_stuff (info);
150 info->next_idx = 100;
151 handle->info = g_list_prepend (handle->info, info);
153 info->nmethods = image->tables [MONO_TABLE_METHOD].rows + 1;
154 info->mlines = g_new0 (int, info->nmethods);
155 debug_load_method_lines (info);
160 mono_debug_make_symbols (MonoDebugHandle* debug)
164 AssemblyDebugInfo* info;
166 for (tmp = debug->info; tmp; tmp = tmp->next) {
167 info = (AssemblyDebugInfo*)tmp->data;
168 /* yes, it's completely unsafe */
169 buf = g_strdup_printf ("as %s -o /tmp/%s.o", info->filename, info->name);
177 mono_debug_close_ass (AssemblyDebugInfo* debug)
180 g_free (debug->mlines);
181 g_free (debug->name);
182 g_free (debug->filename);
187 mono_debug_close (MonoDebugHandle* debug)
190 AssemblyDebugInfo* info;
192 for (tmp = debug->info; tmp; tmp = tmp->next) {
193 info = (AssemblyDebugInfo*)tmp->data;
194 mono_debug_close_ass (info);
196 g_free (debug->name);
201 mono_debug_add_method (MonoDebugHandle* debug, MonoFlowGraph *cfg)
206 MonoMethod *method = cfg->method;
207 MonoClass *klass = method->klass;
208 MonoMethodSignature *sig = method->signature;
209 char **names = g_new (char*, sig->param_count);
210 AssemblyDebugInfo* info = mono_debug_open_ass (debug, klass->image);
212 /* FIXME: we should mangle the name better */
213 name = g_strdup_printf ("%s%s%s__%s_%p", klass->name_space, klass->name_space [0]? "_": "",
214 klass->name, method->name, method);
216 for (i = 0; name [i]; ++i)
217 if (name [i] == '.') name [i] = '_';
219 mono_class_init (klass);
221 * Find the method index in the image.
223 for (i = 0; klass->methods && i < klass->method.count; ++i) {
224 if (klass->methods [i] == method) {
225 line = info->mlines [klass->method.first + i + 1];
226 /*g_print ("method %d found at line %d\n", klass->method.first + i + 1, line);*/
232 * We need to output all the basic info, if we change filename...
233 * fprintf (info->f, ".stabs \"%s.il\",100,0,0,0\n", klass->image->assembly_name);
235 fprintf (info->f, ".stabs \"%s:F(0,%d)\",36,0,%d,%p\n", name, sig->ret->type, line, cfg->start);
238 mono_method_get_param_names (cfg->method, (const char **)names);
240 fprintf (info->f, ".stabs \"this:p(0,%d)=(0,%d)\",160,0,%d,%d\n", info->next_idx++, klass->byval_arg.type, line, 8); /* FIXME */
241 for (i = 0; i < sig->param_count; ++i) {
242 int stack_offset = g_array_index (cfg->varinfo, MonoVarInfo, cfg->args_start_index + i + sig->hasthis).offset;
243 fprintf (info->f, ".stabs \"%s:p(0,%d)=(0,%d)\",160,0,%d,%d\n", names [i], info->next_idx++, sig->params [i]->type, line, stack_offset);
246 if (!method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
247 MonoMethodHeader *header = ((MonoMethodNormal*)method)->header;
248 for (i = 0; i < header->num_locals; ++i) {
249 int stack_offset = g_array_index (cfg->varinfo, MonoVarInfo, cfg->locals_start_index + i).offset;
250 fprintf (info->f, ".stabs \"local_%d:(0,%d)=(0,%d)\",128,0,%d,%d\n", i, info->next_idx++, header->locals [i]->type, line, stack_offset);
253 /* start lines of basic blocks */
254 for (i = 0; i < cfg->block_count; ++i) {
256 for (j = 0; j < cfg->bblocks [i].forest->len; ++j) {
257 MBTree *t = (MBTree *) g_ptr_array_index (cfg->bblocks [i].forest, j);
258 fprintf (info->f, ".stabn 68,0,%d,%d\n", line + t->cli_addr, t->addr);
262 /* end of function */
263 fprintf (info->f, ".stabs \"\",36,0,0,%d\n", cfg->code - cfg->start);
270 get_enumvalue (MonoClass *klass, int index, char *buf)
272 guint32 const_cols [MONO_CONSTANT_SIZE];
274 guint32 crow = mono_metadata_get_constant_index (klass->image, MONO_TOKEN_FIELD_DEF | (index + 1));
281 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], crow-1, const_cols, MONO_CONSTANT_SIZE);
282 ptr = mono_metadata_blob_heap (klass->image, const_cols [MONO_CONSTANT_VALUE]);
283 switch (const_cols [MONO_CONSTANT_TYPE]) {
286 /* FIXME: add other types... */
288 g_snprintf (buf, 64, "%d", *(gint32*)ptr);
293 mono_debug_add_type (MonoDebugHandle* debug, MonoClass *klass)
298 AssemblyDebugInfo* info = mono_debug_open_ass (debug, klass->image);
300 mono_class_init (klass);
302 /* output enums ...*/
303 if (klass->enumtype) {
304 name = g_strdup_printf ("%s%s%s", klass->name_space, klass->name_space [0]? "_": "", klass->name);
305 fprintf (info->f, ".stabs \"%s:T%d=e", name, ++info->next_idx);
307 for (i = 0; i < klass->field.count; ++i) {
308 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_LITERAL) {
309 get_enumvalue (klass, klass->field.first + i, buf);
310 fprintf (info->f, "%s_%s=%s,", klass->name, klass->fields [i].name, buf);
313 fprintf (info->f, ";\",128,0,0,0\n");