Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] Use dynar instead of dict for storing functions
[simgrid.git] / src / mc / mc_global.c
index b02b11c..987c6fc 100644 (file)
@@ -30,6 +30,7 @@ int _sg_do_model_check = 0;
 int _sg_mc_checkpoint=0;
 char* _sg_mc_property_file=NULL;
 int _sg_mc_timeout=0;
+int _sg_mc_hash=0;
 int _sg_mc_max_depth=1000;
 int _sg_mc_visited=0;
 char *_sg_mc_dot_output_file = NULL;
@@ -70,6 +71,13 @@ void _mc_cfg_cb_timeout(const char *name, int pos) {
   _sg_mc_timeout= xbt_cfg_get_boolean(_sg_cfg_set, name);
 }
 
+void _mc_cfg_cb_hash(const char *name, int pos) {
+  if (_sg_cfg_init_status && !_sg_do_model_check) {
+    xbt_die("You are specifying a value to enable/disable the use of global hash to speedup state comparaison, but model-checking was not activated at config time (through --cfg=model-check:1). This won't work, sorry.");
+  }
+  _sg_mc_hash= xbt_cfg_get_boolean(_sg_cfg_set, name);
+}
+
 void _mc_cfg_cb_max_depth(const char *name, int pos) {
   if (_sg_cfg_init_status && !_sg_do_model_check) {
     xbt_die("You are specifying a max depth value after the initialization (through MSG_config?), but model-checking was not activated at config time (through --cfg=model-check:1). This won't work, sorry.");
@@ -162,7 +170,7 @@ void dw_variable_free(dw_variable_t v){
     xbt_free(v->name);
     xbt_free(v->type_origin);
     if(!v->global)
-      dw_location_free(v->address.location);
+      dw_location_free(v->location);
     xbt_free(v);
   }
 }
@@ -171,11 +179,11 @@ void dw_variable_free_voidp(void *t){
   dw_variable_free((dw_variable_t) * (void **) t);
 }
 
-// object_info
+// ***** object_info
 
 mc_object_info_t MC_new_object_info(void) {
   mc_object_info_t res = xbt_new0(s_mc_object_info_t, 1);
-  res->local_variables = xbt_dict_new_homogeneous(NULL);
+  res->subprograms = xbt_dynar_new(sizeof(dw_frame_t), NULL);
   res->global_variables = xbt_dynar_new(sizeof(dw_variable_t), dw_variable_free_voidp);
   res->types = xbt_dict_new_homogeneous(NULL);
   res->types_by_name = xbt_dict_new_homogeneous(NULL);
@@ -184,14 +192,139 @@ mc_object_info_t MC_new_object_info(void) {
 
 void MC_free_object_info(mc_object_info_t* info) {
   xbt_free(&(*info)->file_name);
-  xbt_dict_free(&(*info)->local_variables);
+  xbt_dynar_free(&(*info)->subprograms);
   xbt_dynar_free(&(*info)->global_variables);
   xbt_dict_free(&(*info)->types);
   xbt_dict_free(&(*info)->types_by_name);
   xbt_free(info);
+  xbt_dynar_free(&(*info)->functions_index);
   *info = NULL;
 }
 
+// ***** Helpers
+
+void* MC_object_base_address(mc_object_info_t info) {
+  void* result = info->start_exec;
+  if(info->start_rw!=NULL && result > (void*) info->start_rw) result = info->start_rw;
+  if(info->start_ro!=NULL && result > (void*) info->start_ro) result = info->start_ro;
+  return result;
+}
+
+// ***** Functions index
+
+static int MC_compare_frame_index_items(mc_function_index_item_t a, mc_function_index_item_t b) {
+  if(a->low_pc < b->low_pc)
+    return -1;
+  else if(a->low_pc == b->low_pc)
+    return 0;
+  else
+    return 1;
+}
+
+static void MC_make_functions_index(mc_object_info_t info) {
+  xbt_dynar_t index = xbt_dynar_new(sizeof(s_mc_function_index_item_t), NULL);
+
+  // Populate the array:
+  dw_frame_t frame = NULL;
+  unsigned cursor = 0;
+  xbt_dynar_foreach(info->subprograms, cursor, frame) {
+    if(frame->low_pc==NULL)
+      continue;
+    s_mc_function_index_item_t entry;
+    entry.low_pc = frame->low_pc;
+    entry.high_pc = frame->high_pc;
+    entry.function = frame;
+    xbt_dynar_push(index, &entry);
+  }
+
+  mc_function_index_item_t base = (mc_function_index_item_t) xbt_dynar_get_ptr(index, 0);
+
+  // Sort the array by low_pc:
+  qsort(base,
+    xbt_dynar_length(index),
+    sizeof(s_mc_function_index_item_t),
+    (int (*)(const void *, const void *))MC_compare_frame_index_items);
+
+  info->functions_index = index;
+}
+
+mc_object_info_t MC_ip_find_object_info(void* ip) {
+  mc_object_info_t infos[2] = { mc_binary_info, mc_libsimgrid_info };
+  size_t n = 2;
+  size_t i;
+  for(i=0; i!=n; ++i) {
+    if(ip >= (void*)infos[i]->start_exec && ip <= (void*)infos[i]->end_exec) {
+      return infos[i];
+    }
+  }
+  return NULL;
+}
+
+static dw_frame_t MC_find_function_by_ip_and_object(void* ip, mc_object_info_t info) {
+  xbt_dynar_t dynar = info->functions_index;
+  mc_function_index_item_t base = (mc_function_index_item_t) xbt_dynar_get_ptr(dynar, 0);
+  int i = 0;
+  int j = xbt_dynar_length(dynar) - 1;
+  while(j>=i) {
+    int k = i + ((j-i)/2);
+    if(ip < base[k].low_pc) {
+      j = k-1;
+    } else if(ip > base[k].high_pc) {
+      i = k+1;
+    } else {
+      return base[k].function;
+    }
+  }
+  return NULL;
+}
+
+dw_frame_t MC_find_function_by_ip(void* ip) {
+  mc_object_info_t info = MC_ip_find_object_info(ip);
+  if(info==NULL)
+    return NULL;
+  else
+    return MC_find_function_by_ip_and_object(ip, info);
+}
+
+static void MC_post_process_variables(mc_object_info_t info) {
+  unsigned cursor = 0;
+  dw_variable_t variable = NULL;
+  xbt_dynar_foreach(info->global_variables, cursor, variable) {
+    if(variable->type_origin) {
+      variable->type = xbt_dict_get_or_null(info->types, variable->type_origin);
+    }
+  }
+}
+
+static void MC_post_process_functions(mc_object_info_t info) {
+  unsigned cursor = 0;
+  dw_frame_t function = NULL;
+  xbt_dynar_foreach(info->subprograms, cursor, function) {
+    unsigned cursor2 = 0;
+    dw_variable_t variable = NULL;
+    xbt_dynar_foreach(function->variables, cursor2, variable) {
+      if(variable->type_origin) {
+        variable->type = xbt_dict_get_or_null(info->types, variable->type_origin);
+      }
+    }
+  }
+}
+
+/** \brief Finds informations about a given shared object/executable */
+mc_object_info_t MC_find_object_info(memory_map_t maps, char* name, int executable) {
+  mc_object_info_t result = MC_new_object_info();
+  if(executable)
+    result->flags |= MC_OBJECT_INFO_EXECUTABLE;
+  result->file_name = xbt_strdup(name);
+  MC_find_object_address(maps, result);
+  MC_dwarf_get_variables(result);
+  MC_post_process_types(result);
+  MC_post_process_variables(result);
+  MC_post_process_functions(result);
+  MC_make_functions_index(result);
+  return result;
+}
+
 /*************************************************************************/
 
 static dw_location_t MC_dwarf_get_location(xbt_dict_t location_list, char *expr){
@@ -385,9 +518,9 @@ static int MC_dwarf_get_variable_index(xbt_dynar_t variables, char* var, void *a
       end = cursor - 1;
     }else{
       if(address){ /* global variable */
-        if(var_test->address.address == address)
+        if(var_test->address == address)
           return -1;
-        if(var_test->address.address > address)
+        if(var_test->address > address)
           end = cursor - 1;
         else
           start = cursor + 1;
@@ -398,7 +531,7 @@ static int MC_dwarf_get_variable_index(xbt_dynar_t variables, char* var, void *a
   }
 
   if(strcmp(var_test->name, var) == 0){
-    if(address && var_test->address.address < address)
+    if(address && var_test->address < address)
       return cursor+1;
     else
       return cursor;
@@ -410,7 +543,7 @@ static int MC_dwarf_get_variable_index(xbt_dynar_t variables, char* var, void *a
 }
 
 void MC_dwarf_register_global_variable(mc_object_info_t info, dw_variable_t variable) {
-  int index = MC_dwarf_get_variable_index(info->global_variables, variable->name, variable->address.address);
+  int index = MC_dwarf_get_variable_index(info->global_variables, variable->name, variable->address);
   if (index != -1)
     xbt_dynar_insert_at(info->global_variables, index, &variable);
   // TODO, else ?
@@ -603,72 +736,50 @@ void MC_ignore_global_variable(const char *name){
     MC_UNSET_RAW_MEM;
 }
 
+static void MC_ignore_local_variable_in_object(const char *var_name, const char *frame_name, mc_object_info_t info) {
+  unsigned cursor2;
+  dw_frame_t frame;
+  int start, end;
+  int cursor = 0;
+  dw_variable_t current_var;
+
+  xbt_dynar_foreach(info->subprograms, cursor2, frame) {
+
+    if(frame_name && strcmp(frame_name, frame->name))
+      continue;
+
+    start = 0;
+    end = xbt_dynar_length(frame->variables) - 1;
+    while(start <= end){
+      cursor = (start + end) / 2;
+      current_var = (dw_variable_t)xbt_dynar_get_as(frame->variables, cursor, dw_variable_t);
+
+      int compare = strcmp(current_var->name, var_name);
+      if(compare == 0){
+        xbt_dynar_remove_at(frame->variables, cursor, NULL);
+        start = 0;
+        end = xbt_dynar_length(frame->variables) - 1;
+      }else if(compare < 0){
+        start = cursor + 1;
+      }else{
+        end = cursor - 1;
+      }
+    }
+  }
+}
+
 void MC_ignore_local_variable(const char *var_name, const char *frame_name){
   
   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
 
+  if(strcmp(frame_name, "*") == 0)
+    frame_name = NULL;
+
   MC_SET_RAW_MEM;
 
-    unsigned int cursor = 0;
-    dw_variable_t current_var;
-    int start, end;
-    if(strcmp(frame_name, "*") == 0){ /* Remove variable in all frames */
-      xbt_dict_cursor_t dict_cursor;
-      char *current_frame_name;
-      dw_frame_t frame;
-      xbt_dict_foreach(mc_libsimgrid_info->local_variables, dict_cursor, current_frame_name, frame){
-        start = 0;
-        end = xbt_dynar_length(frame->variables) - 1;
-        while(start <= end){
-          cursor = (start + end) / 2;
-          current_var = (dw_variable_t)xbt_dynar_get_as(frame->variables, cursor, dw_variable_t); 
-          if(strcmp(current_var->name, var_name) == 0){
-            xbt_dynar_remove_at(frame->variables, cursor, NULL);
-            start = 0;
-            end = xbt_dynar_length(frame->variables) - 1;
-          }else if(strcmp(current_var->name, var_name) < 0){
-            start = cursor + 1;
-          }else{
-            end = cursor - 1;
-          } 
-        }
-      }
-       xbt_dict_foreach(mc_binary_info->local_variables, dict_cursor, current_frame_name, frame){
-        start = 0;
-        end = xbt_dynar_length(frame->variables) - 1;
-        while(start <= end){
-          cursor = (start + end) / 2;
-          current_var = (dw_variable_t)xbt_dynar_get_as(frame->variables, cursor, dw_variable_t); 
-          if(strcmp(current_var->name, var_name) == 0){
-            xbt_dynar_remove_at(frame->variables, cursor, NULL);
-            start = 0;
-            end = xbt_dynar_length(frame->variables) - 1;
-          }else if(strcmp(current_var->name, var_name) < 0){
-            start = cursor + 1;
-          }else{
-            end = cursor - 1;
-          } 
-        }
-      }
-    }else{
-      xbt_dynar_t variables_list = ((dw_frame_t)xbt_dict_get_or_null(
-                                      mc_libsimgrid_info->local_variables, frame_name))->variables;
-      start = 0;
-      end = xbt_dynar_length(variables_list) - 1;
-      while(start <= end){
-        cursor = (start + end) / 2;
-        current_var = (dw_variable_t)xbt_dynar_get_as(variables_list, cursor, dw_variable_t);
-        if(strcmp(current_var->name, var_name) == 0){
-          xbt_dynar_remove_at(variables_list, cursor, NULL);
-          start = 0;
-          end = xbt_dynar_length(variables_list) - 1;
-        }else if(strcmp(current_var->name, var_name) < 0){
-          start = cursor + 1;
-        }else{
-          end = cursor - 1;
-        } 
-      }
-    } 
+  MC_ignore_local_variable_in_object(var_name, frame_name, mc_libsimgrid_info);
+  if(frame_name!=NULL)
+    MC_ignore_local_variable_in_object(var_name, frame_name, mc_binary_info);
 
   if(!raw_mem_set)
     MC_UNSET_RAW_MEM;
@@ -760,15 +871,30 @@ void MC_ignore(void *addr, size_t size){
 /*******************************  Initialisation of MC *******************************/
 /*********************************************************************************/
 
-static void MC_init_debug_info();
-static void MC_init_debug_info() {
+static void MC_post_process_object_info(mc_object_info_t info) {
+  mc_object_info_t other_info = info == mc_binary_info ? mc_libsimgrid_info : mc_binary_info;
+  xbt_dict_cursor_t cursor = NULL;
+  char* key = NULL;
+  dw_type_t type = NULL;
+  xbt_dict_foreach(info->types, cursor, key, type){
+    if(type->name && type->byte_size == 0) {
+      type->other_object_same_type = xbt_dict_get_or_null(other_info->types_by_name, type->name);
+    }
+  }
+}
+
+static void MC_init_debug_info(void) {
   XBT_INFO("Get debug information ...");
 
   memory_map_t maps = MC_get_memory_map();
 
   /* Get local variables for state equality detection */
-  mc_binary_info = MC_find_object_info(maps, xbt_binary_name);
-  mc_libsimgrid_info = MC_find_object_info(maps, libsimgrid_path);
+  mc_binary_info = MC_find_object_info(maps, xbt_binary_name, 1);
+  mc_libsimgrid_info = MC_find_object_info(maps, libsimgrid_path, 0);
+
+  // Use information of the other objects:
+  MC_post_process_object_info(mc_binary_info);
+  MC_post_process_object_info(mc_libsimgrid_info);
 
   MC_free_memory_map(maps);
   XBT_INFO("Get debug information done !");
@@ -803,12 +929,14 @@ void MC_init(){
   MC_ignore_local_variable("_throw_ctx", "*");
   MC_ignore_local_variable("ctx", "*");
 
+  MC_ignore_local_variable("self", "simcall_BODY_mc_snapshot");
   MC_ignore_local_variable("next_context", "smx_ctx_sysv_suspend_serial");
   MC_ignore_local_variable("i", "smx_ctx_sysv_suspend_serial");
 
   /* Ignore local variable about time used for tracing */
   MC_ignore_local_variable("start_time", "*"); 
 
+  MC_ignore_global_variable("compared_pointers");
   MC_ignore_global_variable("mc_comp_times");
   MC_ignore_global_variable("mc_snapshot_comparison_time"); 
   MC_ignore_global_variable("mc_time");