GSList *cie_program;
FILE *fp;
const char *temp_prefix;
- gboolean emit_line, appending, collect_line_info;
+ gboolean emit_line;
GSList *line_info;
int cur_file_index;
};
* Create a DWARF writer object. WRITER is the underlying image writer this
* writer will emit to. IL_FILE is the file where IL code will be dumped to for
* methods which have no line number info. It can be NULL.
- * If APPENDING is TRUE, the output file will be in assembleable state after each
- * call to the _emit_ functions. This is used for XDEBUG. If APPENDING is FALSE,
- * a separate mono_dwarf_writer_close () call is needed to finish the emission of
- * debug information.
*/
MonoDwarfWriter*
-mono_dwarf_writer_create (MonoImageWriter *writer, FILE *il_file, int il_file_start_line, gboolean appending, gboolean emit_line_numbers)
+mono_dwarf_writer_create (MonoImageWriter *writer, FILE *il_file, int il_file_start_line, gboolean emit_line_numbers)
{
MonoDwarfWriter *w = g_new0 (MonoDwarfWriter, 1);
-
- /*
- * The appending flag is needed because we use subsections to order things in
- * the debug info, and:
- * - apple's assembler doesn't support them
- * - the binary writer has problems with subsections+alignment
- * So instead of subsections, we use the _close () function in AOT mode,
- * which writes out things in order.
- */
w->w = writer;
w->il_file = il_file;
w->il_file_line_index = il_file_start_line;
- w->appending = appending;
-
- if (appending)
- g_assert (mono_img_writer_subsections_supported (w->w));
-
- w->emit_line = TRUE;
- if (appending) {
- if (!mono_img_writer_subsections_supported (w->w))
- /* Can't emit line number info without subsections */
- w->emit_line = FALSE;
- } else {
- /* Collect line number info and emit it at once */
- w->collect_line_info = TRUE;
- }
-
- if (!emit_line_numbers) {
- w->emit_line = FALSE;
- w->collect_line_info = FALSE;
- }
+ w->emit_line = emit_line_numbers;
w->fp = mono_img_writer_get_fp (w->w);
w->temp_prefix = mono_img_writer_get_temp_label_prefix (w->w);
mono_img_writer_emit_byte (w->w, val);
}
+static void
+emit_escaped_string (MonoDwarfWriter *w, char *value)
+{
+ int i, len;
+
+ len = strlen (value);
+ for (i = 0; i < len; ++i) {
+ char c = value [i];
+ if (!(isalnum (c))) {
+ switch (c) {
+ case '_':
+ case '-':
+ case ':':
+ case '.':
+ case ',':
+ case '/':
+ case '<':
+ case '>':
+ case '`':
+ case '(':
+ case ')':
+ case '[':
+ case ']':
+ break;
+ default:
+ value [i] = '_';
+ break;
+ }
+ }
+ }
+ mono_img_writer_emit_string (w->w, value);
+}
+
static G_GNUC_UNUSED void
emit_uleb128 (MonoDwarfWriter *w, guint32 value)
{
#define LINE_BASE -5
#define LINE_RANGE 14
-/* Subsections of the .debug_line section */
-#define LINE_SUBSECTION_HEADER 1
-#define LINE_SUBSECTION_INCLUDES 2
-#define LINE_SUBSECTION_FILES 3
-#define LINE_SUBSECTION_DATA 4
-#define LINE_SUBSECTION_END 5
-
-static int
-emit_line_number_file_name (MonoDwarfWriter *w, const char *name,
- gint64 last_mod_time, gint64 file_size)
-{
- int index;
- int dir_index;
- char *basename = NULL;
-
- if (!w->file_to_index)
- w->file_to_index = g_hash_table_new (g_str_hash, g_str_equal);
-
- index = GPOINTER_TO_UINT (g_hash_table_lookup (w->file_to_index, name));
- if (index > 0)
- return index;
-
- if (g_path_is_absolute (name)) {
- char *dir = g_path_get_dirname (name);
-
- if (!w->dir_to_index)
- w->dir_to_index = g_hash_table_new (g_str_hash, g_str_equal);
-
- dir_index = GPOINTER_TO_UINT (g_hash_table_lookup (w->dir_to_index, dir));
- if (dir_index == 0) {
- emit_section_change (w, ".debug_line", LINE_SUBSECTION_INCLUDES);
- emit_string (w, dir);
-
- dir_index = ++ w->line_number_dir_index;
- g_hash_table_insert (w->dir_to_index, g_strdup (dir), GUINT_TO_POINTER (dir_index));
- }
-
- g_free (dir);
-
- basename = g_path_get_basename (name);
- } else {
- dir_index = 0;
- }
-
- emit_section_change (w, ".debug_line", LINE_SUBSECTION_FILES);
-
- if (basename)
- emit_string (w, basename);
- else
- emit_string (w, name);
- emit_uleb128 (w, dir_index);
- emit_byte (w, 0);
- emit_byte (w, 0);
-
- emit_section_change (w, ".debug_line", LINE_SUBSECTION_DATA);
-
- if (basename)
- g_free (basename);
-
- index = ++ w->line_number_file_index;
- g_hash_table_insert (w->file_to_index, g_strdup (name), GUINT_TO_POINTER (index));
-
- return index;
-}
-
static int
get_line_number_file_name (MonoDwarfWriter *w, const char *name)
{
int len, i, j;
len = strlen (name);
- s = g_malloc0 ((len + 1) * 2);
+ s = (char *)g_malloc0 ((len + 1) * 2);
j = 0;
for (i = 0; i < len; ++i) {
if (name [i] == '\\') {
GSList *l;
GSList *info_list;
- g_assert (w->collect_line_info);
-
add_line_number_file_name (w, "<unknown>", 0, 0);
/* Collect files */
info_list = g_slist_reverse (w->line_info);
for (l = info_list; l; l = l->next) {
- MethodLineNumberInfo *info = l->data;
+ MethodLineNumberInfo *info = (MethodLineNumberInfo *)l->data;
MonoDebugMethodInfo *minfo;
GPtrArray *source_file_list;
mono_debug_get_seq_points (minfo, NULL, &source_file_list, NULL, NULL, NULL);
for (i = 0; i < source_file_list->len; ++i) {
- MonoDebugSourceInfo *sinfo = g_ptr_array_index (source_file_list, i);
+ MonoDebugSourceInfo *sinfo = (MonoDebugSourceInfo *)g_ptr_array_index (source_file_list, i);
add_line_number_file_name (w, sinfo->source_file, 0, 0);
}
}
dir_to_index = g_hash_table_new (g_str_hash, g_str_equal);
index_to_dir = g_hash_table_new (NULL, NULL);
for (i = 0; i < w->line_number_file_index; ++i) {
- char *name = g_hash_table_lookup (w->index_to_file, GUINT_TO_POINTER (i + 1));
+ char *name = (char *)g_hash_table_lookup (w->index_to_file, GUINT_TO_POINTER (i + 1));
char *copy;
int dir_index = 0;
/* Includes */
emit_section_change (w, ".debug_line", 0);
for (i = 0; i < w->line_number_dir_index; ++i) {
- char *dir = g_hash_table_lookup (index_to_dir, GUINT_TO_POINTER (i + 1));
+ char *dir = (char *)g_hash_table_lookup (index_to_dir, GUINT_TO_POINTER (i + 1));
emit_string (w, mono_dwarf_escape_path (dir));
}
/* Files */
for (i = 0; i < w->line_number_file_index; ++i) {
- char *name = g_hash_table_lookup (w->index_to_file, GUINT_TO_POINTER (i + 1));
+ char *name = (char *)g_hash_table_lookup (w->index_to_file, GUINT_TO_POINTER (i + 1));
char *basename = NULL, *dir;
int dir_index = 0;
/* Emit line number table */
for (l = info_list; l; l = l->next) {
- MethodLineNumberInfo *info = l->data;
+ MethodLineNumberInfo *info = (MethodLineNumberInfo *)l->data;
MonoDebugMethodJitInfo *dmji;
dmji = mono_debug_find_method (info->method, mono_domain_get ());
char *s, *build_info;
int i;
+ if (!w->emit_line) {
+ emit_section_change (w, ".debug_line", 0);
+ emit_label (w, ".Ldebug_line_section_start");
+ emit_label (w, ".Ldebug_line_start");
+ }
+
w->cie_program = base_unwind_program;
emit_section_change (w, ".debug_abbrev", 0);
emit_int32 (w, 0); /* .debug_abbrev offset */
emit_byte (w, sizeof (gpointer)); /* address size */
- if (mono_img_writer_subsections_supported (w->w) && w->appending) {
- /* Emit this into a separate section so it gets placed at the end */
- emit_section_change (w, ".debug_info", 1);
- emit_byte (w, 0); /* close COMPILE_UNIT */
- emit_label (w, ".Ldebug_info_end");
- emit_section_change (w, ".debug_info", 0);
- }
-
/* Compilation unit */
emit_uleb128 (w, ABBREV_COMPILE_UNIT);
build_info = mono_get_runtime_build_info ();
emit_pointer_value (w, 0);
emit_pointer_value (w, 0);
/* offset into .debug_line section */
- if (w->emit_line)
- emit_symbol_diff (w, ".Ldebug_line_start", ".Ldebug_line_section_start", 0);
- else
- emit_pointer_value (w, 0);
+ emit_symbol_diff (w, ".Ldebug_line_start", ".Ldebug_line_section_start", 0);
/* Base types */
for (i = 0; i < G_N_ELEMENTS (basic_types); ++i) {
void
mono_dwarf_writer_close (MonoDwarfWriter *w)
{
- if (!w->appending) {
- emit_section_change (w, ".debug_info", 0);
- emit_byte (w, 0); /* close COMPILE_UNIT */
- emit_label (w, ".Ldebug_info_end");
- }
+ emit_section_change (w, ".debug_info", 0);
+ emit_byte (w, 0); /* close COMPILE_UNIT */
+ emit_label (w, ".Ldebug_info_end");
- if (w->collect_line_info)
+ if (w->emit_line)
emit_all_line_number_info (w);
}
else
cache = w->class_to_die;
- return g_hash_table_lookup (cache, klass);
+ return (const char *)g_hash_table_lookup (cache, klass);
}
/* Returns the local symbol pointing to the emitted debug info */
else
cache = w->class_to_die;
- die = g_hash_table_lookup (cache, klass);
+ die = (char *)g_hash_table_lookup (cache, klass);
if (die)
return die;
if (t->byref) {
if (t->type == MONO_TYPE_VALUETYPE) {
- tdie = g_hash_table_lookup (w->class_to_pointer_die, klass);
+ tdie = (const char *)g_hash_table_lookup (w->class_to_pointer_die, klass);
}
else {
tdie = get_class_die (w, klass, FALSE);
} else {
switch (t->type) {
case MONO_TYPE_CLASS:
- tdie = g_hash_table_lookup (w->class_to_reference_die, klass);
+ tdie = (const char *)g_hash_table_lookup (w->class_to_reference_die, klass);
//tdie = ".LDIE_OBJECT";
break;
case MONO_TYPE_ARRAY:
break;
case MONO_TYPE_GENERICINST:
if (!MONO_TYPE_ISSTRUCT (t)) {
- tdie = g_hash_table_lookup (w->class_to_reference_die, klass);
+ tdie = (const char *)g_hash_table_lookup (w->class_to_reference_die, klass);
} else {
tdie = ".LDIE_I4";
}
case CEE_CASTCLASS:
case CEE_LDELEMA:
if (method->wrapper_type) {
- klass = data;
+ klass = (MonoClass *)data;
} else {
klass = mono_class_get_checked (method->klass->image, token, &error);
g_assert (mono_error_ok (&error)); /* FIXME error handling */
case CEE_NEWOBJ:
case CEE_CALL:
case CEE_CALLVIRT:
- if (method->wrapper_type)
- cmethod = data;
- else
- cmethod = mono_get_method_full (method->klass->image, token, NULL, NULL);
+ if (method->wrapper_type) {
+ cmethod = (MonoMethod *)data;
+ } else {
+ MonoError error;
+ cmethod = mono_get_method_checked (method->klass->image, token, NULL, NULL, &error);
+ if (!cmethod)
+ g_error ("Could not load method due to %s", mono_error_get_message (&error)); /* FIXME don't swallow the error */
+ }
desc = mono_method_full_name (cmethod, TRUE);
res = g_strdup_printf ("<%s>", desc);
g_free (desc);
break;
case CEE_CALLI:
if (method->wrapper_type) {
- desc = mono_signature_get_desc (data, FALSE);
+ desc = mono_signature_get_desc ((MonoMethodSignature *)data, FALSE);
res = g_strdup_printf ("<%s>", desc);
g_free (desc);
} else {
case CEE_STFLD:
case CEE_STSFLD:
if (method->wrapper_type) {
- field = data;
+ field = (MonoClassField *)data;
} else {
field = mono_field_from_token_checked (method->klass->image, token, &klass, NULL, &error);
g_assert (mono_error_ok (&error)); /* FIXME error handling */
static char*
disasm_ins (MonoMethod *method, const guchar *ip, const guint8 **endip)
{
+ MonoError error;
char *dis;
MonoDisHelper dh;
- MonoMethodHeader *header = mono_method_get_header (method);
+ MonoMethodHeader *header = mono_method_get_header_checked (method, &error);
+ mono_error_assert_ok (&error); /* FIXME don't swallow the error */
memset (&dh, 0, sizeof (dh));
dh.newline = "";
guint8 *code, guint32 code_size,
MonoDebugMethodJitInfo *debug_info)
{
+ MonoError error;
guint32 prev_line = 0;
guint32 prev_native_offset = 0;
int i, file_index, il_offset, prev_il_offset;
gboolean first = TRUE;
MonoDebugSourceLocation *loc;
char *prev_file_name = NULL;
- MonoMethodHeader *header = mono_method_get_header (method);
+ MonoMethodHeader *header = mono_method_get_header_checked (method, &error);
MonoDebugMethodInfo *minfo;
MonoDebugLineNumberEntry *ln_array;
int *native_to_il_offset = NULL;
+ mono_error_assert_ok (&error); /* FIXME don't swallow the error */
+
if (!w->emit_line) {
mono_metadata_free_mh (header);
return;
ln_array = g_new0 (MonoDebugLineNumberEntry, debug_info->num_line_numbers);
memcpy (ln_array, debug_info->line_numbers, debug_info->num_line_numbers * sizeof (MonoDebugLineNumberEntry));
- qsort (ln_array, debug_info->num_line_numbers, sizeof (MonoDebugLineNumberEntry), (gpointer)compare_lne);
+ qsort (ln_array, debug_info->num_line_numbers, sizeof (MonoDebugLineNumberEntry), (int (*)(const void *, const void *))compare_lne);
native_to_il_offset = g_new0 (int, code_size + 1);
addr_diff = i - prev_native_offset;
if (first) {
- emit_section_change (w, ".debug_line", LINE_SUBSECTION_DATA);
+ emit_section_change (w, ".debug_line", 0);
emit_byte (w, 0);
emit_byte (w, sizeof (gpointer) + 1);
if (!prev_file_name || strcmp (loc->source_file, prev_file_name) != 0) {
/* Add an entry to the file table */
/* FIXME: Avoid duplicates */
- if (w->collect_line_info)
- file_index = get_line_number_file_name (w, loc->source_file) + 1;
- else
- file_index = emit_line_number_file_name (w, loc->source_file, 0, 0);
+ file_index = get_line_number_file_name (w, loc->source_file) + 1;
g_free (prev_file_name);
prev_file_name = g_strdup (loc->source_file);
il_to_line = g_new0 (int, header->code_size);
- emit_section_change (w, ".debug_line", LINE_SUBSECTION_DATA);
+ emit_section_change (w, ".debug_line", 0);
emit_byte (w, 0);
emit_byte (w, sizeof (gpointer) + 1);
emit_byte (w, DW_LNE_set_address);
mono_dwarf_writer_emit_method (MonoDwarfWriter *w, MonoCompile *cfg, MonoMethod *method, char *start_symbol, char *end_symbol, char *linkage_name,
guint8 *code, guint32 code_size, MonoInst **args, MonoInst **locals, GSList *unwind_info, MonoDebugMethodJitInfo *debug_info)
{
+ MonoError error;
char *name;
MonoMethodSignature *sig;
MonoMethodHeader *header;
emit_section_change (w, ".debug_info", 0);
sig = mono_method_signature (method);
- header = mono_method_get_header (method);
+ header = mono_method_get_header_checked (method, &error);
+ mono_error_assert_ok (&error); /* FIXME don't swallow the error */
/* Parameter types */
for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
emit_uleb128 (w, ABBREV_SUBPROGRAM);
/* DW_AT_name */
name = mono_method_full_name (method, FALSE);
- emit_string (w, name);
+ emit_escaped_string (w, name);
/* DW_AT_MIPS_linkage_name */
if (linkage_name)
emit_string (w, linkage_name);
w->fde_index ++;
}
- /* Emit line number info */
+ /* Save the information needed to emit the line number info later at once */
/* != could happen when using --regression */
if (debug_info && (debug_info->code_start == code)) {
- if (w->collect_line_info) {
- MethodLineNumberInfo *info;
-
- /* Save the information needed to emit the line number info later at once */
- info = g_new0 (MethodLineNumberInfo, 1);
- info->method = method;
- info->start_symbol = g_strdup (start_symbol);
- info->end_symbol = g_strdup (end_symbol);
- info->code = code;
- info->code_size = code_size;
- w->line_info = g_slist_prepend (w->line_info, info);
- } else {
- emit_line_number_info (w, method, start_symbol, end_symbol, code, code_size, debug_info);
- }
+ MethodLineNumberInfo *info;
+
+ info = g_new0 (MethodLineNumberInfo, 1);
+ info->method = method;
+ info->start_symbol = g_strdup (start_symbol);
+ info->end_symbol = g_strdup (end_symbol);
+ info->code = code;
+ info->code_size = code_size;
+ w->line_info = g_slist_prepend (w->line_info, info);
}
emit_line (w);