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>
9 #include "debug-private.h"
18 * Note: same order of MonoTypeEnum.
24 {"Boolean", ";0;255;"},
25 {"Char", ";0;65535;"},
26 {"SByte", ";-128;127;"},
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*/
40 {"Class", "(0,44)=*(0,45)=xsMonoObject:"}, /*class*/
42 {"Array", }, /*array*/
43 {"", }, /*typedbyref*/
46 {"IntPtr", ";0020000000000;0017777777777;"},
47 {"UIntPtr", ";0000000000000;0037777777777;"},
49 {"FnPtr", "*(0,1)"}, /*fnptr*/
50 {"Object", "(0,47)=*(0,48)=xsMonoObject:"}, /*object*/
51 {"SzArray", "(0,50)=*(0,51))=xsMonoArray:"}, /*szarray*/
56 mono_debug_open_assembly_stabs (AssemblyDebugInfo* info)
61 mono_debug_close_assembly_stabs (AssemblyDebugInfo* info)
66 write_method_stabs (AssemblyDebugInfo *info, DebugMethodInfo *minfo)
69 MonoMethod *method = minfo->method_info.method;
70 MonoClass *klass = method->klass;
71 MonoMethodSignature *sig = method->signature;
72 char **names = g_new (char*, sig->param_count);
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);
78 fprintf (info->f, ".stabs \"%s:F(0,%d)\",36,0,%d,%p\n", minfo->name, sig->ret->type,
79 minfo->start_line, minfo->method_info.code_start);
82 mono_method_get_param_names (method, (const char **)names);
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,
86 minfo->method_info.this_offset);
87 for (i = 0; i < minfo->method_info.num_params; i++) {
88 int stack_offset = minfo->method_info.param_offsets [i];
90 fprintf (info->f, ".stabs \"%s:p(0,%d)=(0,%d)\",160,0,%d,%d\n",
91 names [i], info->next_idx++, sig->params [i]->type,
92 minfo->start_line, stack_offset);
96 for (i = 0; i < minfo->method_info.num_locals; ++i) {
97 MonoMethodHeader *header = ((MonoMethodNormal*)method)->header;
98 int stack_offset = minfo->method_info.local_offsets [i];
100 fprintf (info->f, ".stabs \"local_%d:(0,%d)=(0,%d)\",128,0,%d,%d\n",
101 i, info->next_idx++, header->locals [i]->type, minfo->start_line, stack_offset);
104 if (minfo->line_numbers) {
105 fprintf (info->f, ".stabn 68,0,%d,%d\n", minfo->start_line, 0);
107 for (i = 1; i < minfo->line_numbers->len; i++) {
108 DebugLineNumberInfo *lni = g_ptr_array_index (minfo->line_numbers, i);
110 fprintf (info->f, ".stabn 68,0,%d,%d\n", lni->line,
111 lni->address - minfo->method_info.code_start);
115 /* end of function */
116 fprintf (info->f, ".stabs \"\",36,0,0,%d\n", minfo->method_info.code_size);
123 get_enumvalue (MonoClass *klass, int index, char *buf)
125 guint32 const_cols [MONO_CONSTANT_SIZE];
127 guint32 crow = mono_metadata_get_constant_index (klass->image, MONO_TOKEN_FIELD_DEF | (index + 1));
134 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], crow-1, const_cols, MONO_CONSTANT_SIZE);
135 ptr = mono_metadata_blob_heap (klass->image, const_cols [MONO_CONSTANT_VALUE]);
136 switch (const_cols [MONO_CONSTANT_TYPE]) {
139 /* FIXME: add other types... */
141 g_snprintf (buf, 64, "%d", *(gint32*)ptr);
146 write_method_func (gpointer key, gpointer value, gpointer user_data)
148 write_method_stabs (user_data, value);
152 write_class_stabs (AssemblyDebugInfo *info, MonoClass *klass, int index)
158 /* output enums ...*/
159 if (klass->enumtype) {
160 name = g_strdup_printf ("%s%s%s", klass->name_space, klass->name_space [0]? "_": "", klass->name);
161 fprintf (info->f, ".stabs \"%s:T%d=e", name, ++info->next_idx);
163 for (i = 0; i < klass->field.count; ++i) {
164 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_LITERAL) {
165 get_enumvalue (klass, klass->field.first + i, buf);
166 fprintf (info->f, "%s_%s=%s,", klass->name, klass->fields [i].name, buf);
169 fprintf (info->f, ";\",128,0,0,0\n");
175 write_class (gpointer key, gpointer value, gpointer user_data)
177 write_class_stabs (user_data, key, GPOINTER_TO_INT (value));
181 mono_debug_write_assembly_stabs (AssemblyDebugInfo* info)
186 if (!(info->f = fopen (info->filename, "w")))
189 for (i = 0; base_types [i].name; ++i) {
190 if (! base_types [i].spec)
192 fprintf (info->f, ".stabs \"%s:t(0,%d)=", base_types [i].name, i);
193 if (base_types [i].spec [0] == ';') {
194 fprintf (info->f, "r(0,%d)%s\"", i, base_types [i].spec);
196 fprintf (info->f, "%s\"", base_types [i].spec);
198 fprintf (info->f, ",128,0,0,0\n");
201 g_hash_table_foreach (info->methods, write_method_func, info);
203 g_hash_table_foreach (info->type_hash, write_class, info);
208 /* yes, it's completely unsafe */
209 buf = g_strdup_printf ("as %s -o /tmp/%s.o", info->filename, info->name);