diff options
Diffstat (limited to 'mixlib')
-rw-r--r-- | mixlib/mix_vm.c | 50 | ||||
-rw-r--r-- | mixlib/mix_vm.h | 12 | ||||
-rw-r--r-- | mixlib/xmix_vm.h | 3 | ||||
-rw-r--r-- | mixlib/xmix_vm_handlers.c | 45 | ||||
-rw-r--r-- | mixlib/xmix_vm_handlers.h | 1 |
5 files changed, 91 insertions, 20 deletions
diff --git a/mixlib/mix_vm.c b/mixlib/mix_vm.c index d714bba..94eae1e 100644 --- a/mixlib/mix_vm.c +++ b/mixlib/mix_vm.c @@ -81,8 +81,8 @@ vm_reset_reload_ (mix_vm_t *vm, gboolean is_reload) if (vm->address_list) { - g_slist_free (vm->address_list); - vm->address_list = NULL; + g_queue_free (vm->address_list); + vm->address_list = g_queue_new (); } } @@ -99,7 +99,8 @@ mix_vm_new (void) vm->symbol_table = NULL; vm->src_file = NULL; vm->pred_list = mix_predicate_list_new (vm); - vm->address_list = NULL; + vm->max_backtrace_amount = MIX_MAX_TRACE_AMOUNT; + vm->address_list = g_queue_new (); vm->last_error = MIX_VM_ERROR_NONE; for (i = 0; i < BD_NO_; ++i) @@ -126,7 +127,7 @@ mix_vm_delete (mix_vm_t * vm) if (vm->symbol_table != NULL) mix_symbol_table_delete (vm->symbol_table); if (vm->src_file != NULL) mix_src_file_delete (vm->src_file); if (vm->pred_list != NULL) mix_predicate_list_delete (vm->pred_list); - if (vm->address_list != NULL) g_slist_free (vm->address_list); + if (vm->address_list != NULL) g_queue_free (vm->address_list); for (i = 0; i < BD_NO_; ++i) mix_device_delete (vm->devices[i]); mix_vm_clock_delete (vm->clock); @@ -452,9 +453,14 @@ mix_vm_run (mix_vm_t *vm) while ( !is_halted_ (vm) ) { mix_word_to_ins_uncheck (get_cell_ (vm, get_loc_ (vm)), ins); - vm->address_list = - g_slist_prepend (vm->address_list, - GINT_TO_POINTER ((gint)get_loc_ (vm))); + if ( vm->max_backtrace_amount != 0 ) { + g_queue_push_head (vm->address_list, + GINT_TO_POINTER ((gint)get_loc_ (vm))); + if ( vm->max_backtrace_amount > 0 && + g_queue_get_length (vm->address_list) > vm->max_backtrace_amount ) { + g_queue_pop_tail (vm->address_list); + } + } if ( !(*ins_handlers_[ins.opcode]) (vm,&ins) ) return set_status_ (vm, MIX_VM_ERROR); else @@ -476,9 +482,14 @@ mix_vm_exec_next (mix_vm_t *vm) g_return_val_if_fail (vm != NULL, MIX_VM_ERROR); if (get_loc_ (vm) >= MIX_VM_CELL_NO) halt_ (vm, TRUE); if (is_halted_ (vm)) return set_status_ (vm, MIX_VM_HALT); - vm->address_list = - g_slist_prepend (vm->address_list, - GINT_TO_POINTER ((gint)get_loc_ (vm))); + if ( vm->max_backtrace_amount != 0 ) { + g_queue_push_head (vm->address_list, + GINT_TO_POINTER ((gint)get_loc_ (vm))); + if ( vm->max_backtrace_amount > 0 && + g_queue_get_length (vm->address_list) > vm->max_backtrace_amount ) { + g_queue_pop_tail (vm->address_list); + } + } mix_word_to_ins_uncheck (get_cell_ (vm, get_loc_ (vm)), ins); if (!(*ins_handlers_[ins.opcode]) (vm, &ins)) return set_status_ (vm, MIX_VM_ERROR); @@ -698,9 +709,24 @@ mix_vm_get_uptime (const mix_vm_t *vm) } /* Get the list of addresses for executed instructions */ -const GSList * +GQueue * mix_vm_get_backtrace (const mix_vm_t *vm) { g_return_val_if_fail (vm != NULL, NULL); - return get_address_list_ (vm); + return vm->address_list; +} + +gint +mix_vm_get_max_trace (const mix_vm_t *vm) +{ + g_return_val_if_fail (vm != NULL, -2); + return vm->max_backtrace_amount; +} + +void +mix_vm_set_max_trace (mix_vm_t *vm, gint val) +{ + g_return_if_fail (vm != NULL); + g_return_if_fail (val >= -1); + vm->max_backtrace_amount = val; } diff --git a/mixlib/mix_vm.h b/mixlib/mix_vm.h index 0f4e690..4b07164 100644 --- a/mixlib/mix_vm.h +++ b/mixlib/mix_vm.h @@ -34,6 +34,9 @@ /* Comparison flag */ typedef enum { mix_LESS, mix_EQ, mix_GREAT } mix_cmpflag_t; +/* Maximum number of addresses for backtraces: -1 = unlimited, 0 = off */ +enum { MIX_MAX_TRACE_AMOUNT = 500 }; + /* Number of memory cells in the virtual machine */ enum { MIX_VM_CELL_NO = 4000 }; @@ -247,9 +250,16 @@ extern mix_time_t mix_vm_get_uptime (const mix_vm_t *vm); /* Get the list of addresses for executed instructions */ -extern const GSList * +extern GQueue * mix_vm_get_backtrace (const mix_vm_t *vm); +/* Get the maximum number of instructions we will trace */ +gint +mix_vm_get_max_trace (const mix_vm_t *vm); + +/* Set the maximum number of instructions we will trace */ +void +mix_vm_set_max_trace (mix_vm_t *vm, gint val); #endif /* MIX_VM_H */ diff --git a/mixlib/xmix_vm.h b/mixlib/xmix_vm.h index 0d6605f..34dedd7 100644 --- a/mixlib/xmix_vm.h +++ b/mixlib/xmix_vm.h @@ -50,6 +50,7 @@ struct mix_vm_t mix_vm_status_t status; mix_vm_error_t last_error; mix_device_t * devices[BD_NO_]; + gint max_backtrace_amount; /* the limit of backtraces */ mix_address_t start_addr; /* start address of loaded file */ GTree *line_table; /* source line no -> address */ GTree *address_table; /* adress -> source line no */ @@ -59,7 +60,7 @@ struct mix_vm_t mix_src_file_t *src_file; /* source of last loaded code file */ mix_device_factory_t factory; /* the factory for new devices */ mix_predicate_list_t *pred_list; /* predicates for conditional bps */ - GSList *address_list; /* list of executed addresses */ + GQueue *address_list; /* list of executed addresses */ }; /* Macros for accessing/modifying the above structure. diff --git a/mixlib/xmix_vm_handlers.c b/mixlib/xmix_vm_handlers.c index c964116..f356607 100644 --- a/mixlib/xmix_vm_handlers.c +++ b/mixlib/xmix_vm_handlers.c @@ -86,6 +86,8 @@ mix_vm_command_info_t commands_[] = { "strace on|off"}, { "pbt", cmd_pbt_, N_("Print backtrace of executed instructions"), "pbt [INS_NO] (e.g pbt 5)"}, + { "sbt", cmd_sbt_, N_("Set limit on backtrace of executed instructions"), + "sbt [LIMIT] (e.g sbt 100)"}, { "stime", cmd_stime_, N_("Turn on/off timing statistics"), "stime on|off"}, { "ptime", cmd_ptime_, N_("Print current time statistics"), "ptime"}, @@ -1306,6 +1308,7 @@ gboolean cmd_pbt_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) { enum {SIZE = 256}; + static const gchar *NULLSTR = "(null)"; static gchar BUFFER[SIZE]; gint no = atoi (arg); gint k = 0, address; @@ -1314,29 +1317,59 @@ cmd_pbt_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) char *name = file ? g_path_get_basename (mix_src_file_get_path (file)) : NULL; - const GSList *add = mix_vm_get_backtrace (dis->vm); - while (add && (no == 0 || k < no)) + GQueue *add = mix_vm_get_backtrace (dis->vm); + while (g_queue_get_length (add) > k && (no == 0 || k < no)) { BUFFER[0] = '\0'; - address = GPOINTER_TO_INT (add->data); + address = GPOINTER_TO_INT (g_queue_peek_nth (add, k)); line = mix_vm_get_address_lineno (dis->vm, address); if (line && file) { int j = 0; g_snprintf (BUFFER, SIZE, "%s", mix_src_file_get_line (file, line)); - while (!isspace (BUFFER[j])) j++; + while ( (j < SIZE - 1) && (BUFFER[j] != '\n') && (BUFFER[j] != '\r') + && (BUFFER[j] != '\f') && (BUFFER[j] != '\0') ) j++; BUFFER[j] = '\0'; } - if (strlen (BUFFER) == 0) g_snprintf (BUFFER, SIZE, "%d", address); + if ( (strlen (BUFFER) == 0) || !(strcmp(NULLSTR,BUFFER)) ) + g_snprintf (BUFFER, SIZE, "%d", address); fprintf (dis->out, "#%d\t%s\tin %s%s:%d\n", k, BUFFER, name, MIX_SRC_DEFEXT, line); ++k; - add = add->next; } return TRUE; } gboolean +cmd_sbt_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + gint no = atoi (arg); + GQueue *add = mix_vm_get_backtrace (dis->vm); + + if ( strlen(arg) == 0 ) { + log_message_ (dis, "Backtrace limit is %d instructions", + mix_vm_get_max_trace(dis->vm)); + } else { + if ( no >= -1 ) { + log_message_ (dis, "Backtrace limit changed from %d to %d instructions", + mix_vm_get_max_trace(dis->vm), no); + mix_vm_set_max_trace (dis->vm, no); + + /* We might have shrunk the queue and need to resize it */ + if ( no >= 0 ) { + while ( g_queue_get_length (add) > no ) { + g_queue_pop_tail(add); + } + } + + } else { + log_error_ (dis, "Error: %d is not a valid number of instructions.", no); + } + } + return TRUE; +} + +gboolean cmd_slog_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) { static const gchar *ON = "on"; diff --git a/mixlib/xmix_vm_handlers.h b/mixlib/xmix_vm_handlers.h index decdd24..be276d4 100644 --- a/mixlib/xmix_vm_handlers.h +++ b/mixlib/xmix_vm_handlers.h @@ -71,6 +71,7 @@ DEC_FUN (cbpm_); DEC_FUN (cbpc_); DEC_FUN (cbpo_); DEC_FUN (pbt_); +DEC_FUN (sbt_); DEC_FUN (slog_); DEC_FUN (pprog_); DEC_FUN (psrc_); |