2002-03-14 Martin Baulig <martin@gnome.org>
[mono.git] / mono / jit / debug-stabs.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include <mono/metadata/class.h>
4 #include <mono/metadata/tabledefs.h>
5 #include <mono/metadata/tokentype.h>
6 #include <mono/jit/codegen.h>
7 #include <mono/jit/debug.h>
8
9 #include "debug-private.h"
10
11 typedef struct {
12         char *name;
13         char *spec;
14 } BaseTypes;
15
16 /*
17  * Not 64 bit clean.
18  * Note: same order of MonoTypeEnum.
19  */
20 static BaseTypes
21 base_types[] = {
22         {"", NULL},
23         {"Void", "(0,1)"},
24         {"Boolean", ";0;255;"},
25         {"Char", ";0;65535;"},
26         {"SByte", ";-128;127;"},
27         {"Byte", ";0;255;"},
28         {"Int16", ";-32768;32767;"},
29         {"UInt16", ";0;65535;"},
30         {"Int32", ";0020000000000;0017777777777;"},
31         {"UInt32", ";0000000000000;0037777777777;"},
32         {"Int64", ";01000000000000000000000;0777777777777777777777;"},
33         {"UInt64", ";0000000000000;01777777777777777777777;"},
34         {"Single", "r(0,8);4;0;"},
35         {"Double", "r(0,8);8;0;"},
36         {"String", "(0,41)=*(0,42)=xsMonoString:"}, /*string*/
37         {"", }, /*ptr*/
38         {"", }, /*byref*/
39         {"", }, /*valuetype*/
40         {"Class", "(0,44)=*(0,45)=xsMonoObject:"}, /*class*/
41         {"", }, /*unused*/
42         {"Array", }, /*array*/
43         {"", }, /*typedbyref*/
44         {"", }, /*unused*/
45         {"", }, /*unused*/
46         {"IntPtr", ";0020000000000;0017777777777;"},
47         {"UIntPtr", ";0000000000000;0037777777777;"},
48         {"", }, /*unused*/
49         {"FnPtr", "*(0,1)"}, /*fnptr*/
50         {"Object", "(0,47)=*(0,48)=xsMonoObject:"}, /*object*/
51         {"SzArray", "(0,50)=*(0,51))=xsMonoArray:"}, /*szarray*/
52         {NULL, NULL}
53 };
54
55 void
56 mono_debug_open_assembly_stabs (AssemblyDebugInfo* info)
57 {
58 }
59
60 void
61 mono_debug_close_assembly_stabs (AssemblyDebugInfo* info)
62 {
63 }
64
65 static void
66 write_method_stabs (AssemblyDebugInfo *info, DebugMethodInfo *minfo)
67 {
68         int i;
69         MonoMethod *method = minfo->method;
70         MonoClass *klass = method->klass;
71         MonoMethodSignature *sig = method->signature;
72         char **names = g_new (char*, sig->param_count);
73
74         /*
75          * We need to output all the basic info, if we change filename...
76          * fprintf (info->f, ".stabs \"%s.il\",100,0,0,0\n", klass->image->assembly_name);
77          */
78         fprintf (info->f, ".stabs \"%s:F(0,%d)\",36,0,%d,%p\n", minfo->name, sig->ret->type,
79                  minfo->start_line, minfo->code_start);
80
81         /* params */
82         mono_method_get_param_names (method, (const char **)names);
83         if (sig->hasthis)
84                 fprintf (info->f, ".stabs \"this:p(0,%d)=(0,%d)\",160,0,%d,%d\n",
85                          info->next_idx++, klass->byval_arg.type, minfo->start_line, 8); /* FIXME */
86         for (i = 0; i < minfo->num_params; i++) {
87                 int stack_offset = minfo->params [i].offset;
88
89                 fprintf (info->f, ".stabs \"%s:p(0,%d)=(0,%d)\",160,0,%d,%d\n",
90                          names [i], info->next_idx++, sig->params [i]->type,
91                          minfo->start_line, stack_offset);
92         }
93
94         /* local vars */
95         for (i = 0; i < minfo->num_locals; ++i) {
96                 MonoMethodHeader *header = ((MonoMethodNormal*)method)->header;
97                 int stack_offset = minfo->locals [i].offset;
98
99                 fprintf (info->f, ".stabs \"local_%d:(0,%d)=(0,%d)\",128,0,%d,%d\n",
100                          i, info->next_idx++, header->locals [i]->type, minfo->start_line, stack_offset);
101         }
102
103         fprintf (info->f, ".stabn 68,0,%d,%d\n", minfo->start_line, 0);
104
105         for (i = 1; i < minfo->line_numbers->len; i++) {
106                 DebugLineNumberInfo *lni = g_ptr_array_index (minfo->line_numbers, i);
107
108                 fprintf (info->f, ".stabn 68,0,%d,%d\n", lni->line, lni->address - minfo->code_start);
109         }
110
111         /* end of function */
112         fprintf (info->f, ".stabs \"\",36,0,0,%d\n", minfo->code_size);
113
114         g_free (names);
115         fflush (info->f);
116 }
117
118 static void
119 get_enumvalue (MonoClass *klass, int index, char *buf)
120 {
121         guint32 const_cols [MONO_CONSTANT_SIZE];
122         const char *ptr;
123         guint32 crow = mono_metadata_get_constant_index (klass->image, MONO_TOKEN_FIELD_DEF | (index + 1));
124
125         if (!crow) {
126                 buf [0] = '0';
127                 buf [1] = 0;
128                 return;
129         }
130         mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], crow-1, const_cols, MONO_CONSTANT_SIZE);
131         ptr = mono_metadata_blob_heap (klass->image, const_cols [MONO_CONSTANT_VALUE]);
132         switch (const_cols [MONO_CONSTANT_TYPE]) {
133         case MONO_TYPE_U4:
134         case MONO_TYPE_I4:
135                 /* FIXME: add other types... */
136         default:
137                 g_snprintf (buf, 64, "%d", *(gint32*)ptr);
138         }
139 }
140
141 static void
142 write_method_func (gpointer key, gpointer value, gpointer user_data)
143 {
144         write_method_stabs (user_data, value);
145 }
146
147 static void
148 write_class_stabs (AssemblyDebugInfo *info, MonoClass *klass, int index)
149 {
150         char *name;
151         int i;
152         char buf [64];
153
154         /* output enums ...*/
155         if (klass->enumtype) {
156                 name = g_strdup_printf ("%s%s%s", klass->name_space, klass->name_space [0]? "_": "", klass->name);
157                 fprintf (info->f, ".stabs \"%s:T%d=e", name, ++info->next_idx);
158                 g_free (name);
159                 for (i = 0; i < klass->field.count; ++i) {
160                         if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_LITERAL) {
161                                 get_enumvalue (klass, klass->field.first + i, buf);
162                                 fprintf (info->f, "%s_%s=%s,", klass->name, klass->fields [i].name, buf);
163                         }
164                 }
165                 fprintf (info->f, ";\",128,0,0,0\n");
166         }
167         fflush (info->f);
168 }
169
170 static void
171 write_class (gpointer key, gpointer value, gpointer user_data)
172 {
173         write_class_stabs (user_data, key, GPOINTER_TO_INT (value));
174 }
175
176 void
177 mono_debug_write_assembly_stabs (AssemblyDebugInfo* info)
178 {
179         int i;
180         for (i = 0; base_types [i].name; ++i) {
181                 if (! base_types [i].spec)
182                         continue;
183                 fprintf (info->f, ".stabs \"%s:t(0,%d)=", base_types [i].name, i);
184                 if (base_types [i].spec [0] == ';') {
185                         fprintf (info->f, "r(0,%d)%s\"", i, base_types [i].spec);
186                 } else {
187                         fprintf (info->f, "%s\"", base_types [i].spec);
188                 }
189                 fprintf (info->f, ",128,0,0,0\n");
190         }
191
192         g_hash_table_foreach (info->methods, write_method_func, info);
193
194         g_hash_table_foreach (info->type_hash, write_class, info);
195 }