+/* Variables */
+mc_object_info_t mc_libsimgrid_info = NULL;
+mc_object_info_t mc_binary_info = NULL;
+
+/* Ignore mechanism */
+extern xbt_dynar_t mc_heap_comparison_ignore;
+extern xbt_dynar_t stacks_areas;
+
+/* Dot output */
+FILE *dot_output = NULL;
+const char* colors[13];
+
+
+/******************************* DWARF Information *******************************/
+/**********************************************************************************/
+
+/************************** Free functions *************************/
+
+static void dw_location_free(dw_location_t l){
+ if(l){
+ if(l->type == e_dw_loclist)
+ xbt_dynar_free(&(l->location.loclist));
+ else if(l->type == e_dw_compose)
+ xbt_dynar_free(&(l->location.compose));
+ else if(l->type == e_dw_arithmetic)
+ xbt_free(l->location.arithmetic);
+
+ xbt_free(l);
+ }
+}
+
+static void dw_location_entry_free(dw_location_entry_t e){
+ dw_location_free(e->location);
+ xbt_free(e);
+}
+
+void dw_type_free(dw_type_t t){
+ xbt_free(t->name);
+ xbt_free(t->dw_type_id);
+ xbt_dynar_free(&(t->members));
+ xbt_free(t);
+}
+
+static void dw_type_free_voidp(void *t){
+ dw_type_free((dw_type_t) * (void **) t);
+}
+
+void dw_variable_free(dw_variable_t v){
+ if(v){
+ xbt_free(v->name);
+ xbt_free(v->type_origin);
+ if(!v->global)
+ dw_location_free(v->location);
+ xbt_free(v);
+ }
+}
+
+void dw_variable_free_voidp(void *t){
+ dw_variable_free((dw_variable_t) * (void **) t);
+}
+
+// ***** 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->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);
+ return res;
+}
+
+
+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)->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;
+ xbt_dict_cursor_t cursor = NULL;
+ const char* name = NULL;
+ xbt_dict_foreach(info->local_variables, cursor, name, 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) {
+ xbt_dict_cursor_t cursor = NULL;
+ char* key = NULL;
+ dw_frame_t function = NULL;
+ xbt_dict_foreach(info->local_variables, cursor, key, 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){
+
+ dw_location_t loc = xbt_new0(s_dw_location_t, 1);
+
+ if(location_list != NULL){
+
+ char *key = bprintf("%d", (int)strtoul(expr, NULL, 16));
+ loc->type = e_dw_loclist;
+ loc->location.loclist = (xbt_dynar_t)xbt_dict_get_or_null(location_list, key);
+ if(loc->location.loclist == NULL)
+ XBT_INFO("Key not found in loclist");
+ xbt_free(key);
+ return loc;
+
+ }else{
+
+ int cursor = 0;
+ char *tok = NULL, *tok2 = NULL;
+
+ xbt_dynar_t tokens1 = xbt_str_split(expr, ";");
+ xbt_dynar_t tokens2;
+
+ loc->type = e_dw_compose;
+ loc->location.compose = xbt_dynar_new(sizeof(dw_location_t), NULL);
+
+ while(cursor < xbt_dynar_length(tokens1)){
+
+ tok = xbt_dynar_get_as(tokens1, cursor, char*);
+ tokens2 = xbt_str_split(tok, " ");
+ tok2 = xbt_dynar_get_as(tokens2, 0, char*);
+
+ if(strncmp(tok2, "DW_OP_reg", 9) == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_register;
+ new_element->location.reg = atoi(strtok(tok2, "DW_OP_reg"));
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else if(strcmp(tok2, "DW_OP_fbreg:") == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_fbregister_op;
+ new_element->location.fbreg_op = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else if(strncmp(tok2, "DW_OP_breg", 10) == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_bregister_op;
+ new_element->location.breg_op.reg = atoi(strtok(tok2, "DW_OP_breg"));
+ new_element->location.breg_op.offset = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else if(strncmp(tok2, "DW_OP_lit", 9) == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_lit;
+ new_element->location.lit = atoi(strtok(tok2, "DW_OP_lit"));
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else if(strcmp(tok2, "DW_OP_piece:") == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_piece;
+ new_element->location.piece = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else if(strcmp(tok2, "DW_OP_plus_uconst:") == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_plus_uconst;
+ new_element->location.plus_uconst = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char *));
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else if(strcmp(tok, "DW_OP_abs") == 0 ||
+ strcmp(tok, "DW_OP_and") == 0 ||
+ strcmp(tok, "DW_OP_div") == 0 ||
+ strcmp(tok, "DW_OP_minus") == 0 ||
+ strcmp(tok, "DW_OP_mod") == 0 ||
+ strcmp(tok, "DW_OP_mul") == 0 ||
+ strcmp(tok, "DW_OP_neg") == 0 ||
+ strcmp(tok, "DW_OP_not") == 0 ||
+ strcmp(tok, "DW_OP_or") == 0 ||
+ strcmp(tok, "DW_OP_plus") == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_arithmetic;
+ new_element->location.arithmetic = strdup(strtok(tok2, "DW_OP_"));
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else if(strcmp(tok, "DW_OP_stack_value") == 0){
+ }else if(strcmp(tok2, "DW_OP_deref_size:") == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_deref;
+ new_element->location.deref_size = (unsigned int short) atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else if(strcmp(tok, "DW_OP_deref") == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_deref;
+ new_element->location.deref_size = sizeof(void *);
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else if(strcmp(tok2, "DW_OP_constu:") == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_uconstant;
+ new_element->location.uconstant.bytes = 1;
+ new_element->location.uconstant.value = (unsigned long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else if(strcmp(tok2, "DW_OP_consts:") == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_sconstant;
+ new_element->location.sconstant.bytes = 1;
+ new_element->location.sconstant.value = (long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else if(strcmp(tok2, "DW_OP_const1u:") == 0 ||
+ strcmp(tok2, "DW_OP_const2u:") == 0 ||
+ strcmp(tok2, "DW_OP_const4u:") == 0 ||
+ strcmp(tok2, "DW_OP_const8u:") == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_uconstant;
+ new_element->location.uconstant.bytes = tok2[11] - '0';
+ new_element->location.uconstant.value = (unsigned long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else if(strcmp(tok, "DW_OP_const1s") == 0 ||
+ strcmp(tok, "DW_OP_const2s") == 0 ||
+ strcmp(tok, "DW_OP_const4s") == 0 ||
+ strcmp(tok, "DW_OP_const8s") == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_sconstant;
+ new_element->location.sconstant.bytes = tok2[11] - '0';
+ new_element->location.sconstant.value = (long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else{
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_unsupported;
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }
+
+ cursor++;
+ xbt_dynar_free(&tokens2);
+
+ }
+
+ xbt_dynar_free(&tokens1);
+
+ return loc;
+
+ }
+
+}
+
+
+/** \brief Finds a frame (DW_TAG_subprogram) from an DWARF offset in the rangd of this subprogram
+ *
+ * The offset can be an offset of a child DW_TAG_variable.
+ */
+static dw_frame_t MC_dwarf_get_frame_by_offset(xbt_dict_t all_variables, unsigned long int offset){
+
+ xbt_dict_cursor_t cursor = NULL;
+ char *name;
+ dw_frame_t res;
+
+ xbt_dict_foreach(all_variables, cursor, name, res) {
+ if(offset >= res->start && offset < res->end){
+ xbt_dict_cursor_free(&cursor);
+ return res;
+ }
+ }
+
+ xbt_dict_cursor_free(&cursor);
+ return NULL;
+
+}
+
+static dw_variable_t MC_dwarf_get_variable_by_name(dw_frame_t frame, char *var){
+
+ unsigned int cursor = 0;
+ dw_variable_t current_var;
+
+ xbt_dynar_foreach(frame->variables, cursor, current_var){
+ if(strcmp(var, current_var->name) == 0)
+ return current_var;
+ }
+
+ return NULL;
+}
+
+static int MC_dwarf_get_variable_index(xbt_dynar_t variables, char* var, void *address){
+
+ if(xbt_dynar_is_empty(variables))
+ return 0;
+
+ unsigned int cursor = 0;
+ int start = 0;
+ int end = xbt_dynar_length(variables) - 1;
+ dw_variable_t var_test = NULL;
+
+ while(start <= end){
+ cursor = (start + end) / 2;
+ var_test = (dw_variable_t)xbt_dynar_get_as(variables, cursor, dw_variable_t);
+ if(strcmp(var_test->name, var) < 0){
+ start = cursor + 1;
+ }else if(strcmp(var_test->name, var) > 0){
+ end = cursor - 1;
+ }else{
+ if(address){ /* global variable */
+ if(var_test->address == address)
+ return -1;
+ if(var_test->address > address)
+ end = cursor - 1;
+ else
+ start = cursor + 1;
+ }else{ /* local variable */
+ return -1;
+ }
+ }
+ }
+
+ if(strcmp(var_test->name, var) == 0){
+ if(address && var_test->address < address)
+ return cursor+1;
+ else
+ return cursor;
+ }else if(strcmp(var_test->name, var) < 0)
+ return cursor+1;
+ else
+ return cursor;
+
+}
+
+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);
+ if (index != -1)
+ xbt_dynar_insert_at(info->global_variables, index, &variable);
+ // TODO, else ?
+}
+
+void MC_dwarf_register_non_global_variable(mc_object_info_t info, dw_frame_t frame, dw_variable_t variable) {
+ xbt_assert(frame, "Frame is NULL");
+ int index = MC_dwarf_get_variable_index(frame->variables, variable->name, NULL);
+ if (index != -1)
+ xbt_dynar_insert_at(frame->variables, index, &variable);
+ // TODO, else ?
+}
+
+void MC_dwarf_register_variable(mc_object_info_t info, dw_frame_t frame, dw_variable_t variable) {
+ if(variable->global)
+ MC_dwarf_register_global_variable(info, variable);
+ else if(frame==NULL)
+ xbt_die("No frame for this local variable");
+ else
+ MC_dwarf_register_non_global_variable(info, frame, variable);
+}
+
+
+/******************************* Ignore mechanism *******************************/
+/*********************************************************************************/
+
+xbt_dynar_t mc_checkpoint_ignore;
+
+typedef struct s_mc_stack_ignore_variable{
+ char *var_name;
+ char *frame;
+}s_mc_stack_ignore_variable_t, *mc_stack_ignore_variable_t;
+
+/**************************** Free functions ******************************/
+
+static void stack_ignore_variable_free(mc_stack_ignore_variable_t v){
+ xbt_free(v->var_name);
+ xbt_free(v->frame);
+ xbt_free(v);
+}
+
+static void stack_ignore_variable_free_voidp(void *v){
+ stack_ignore_variable_free((mc_stack_ignore_variable_t) * (void **) v);
+}
+
+void heap_ignore_region_free(mc_heap_ignore_region_t r){
+ xbt_free(r);
+}
+
+void heap_ignore_region_free_voidp(void *r){
+ heap_ignore_region_free((mc_heap_ignore_region_t) * (void **) r);
+}
+
+static void checkpoint_ignore_region_free(mc_checkpoint_ignore_region_t r){
+ xbt_free(r);
+}
+
+static void checkpoint_ignore_region_free_voidp(void *r){
+ checkpoint_ignore_region_free((mc_checkpoint_ignore_region_t) * (void **) r);
+}
+
+/***********************************************************************/
+
+void MC_ignore_heap(void *address, size_t size){
+
+ int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
+
+ MC_SET_RAW_MEM;
+
+ mc_heap_ignore_region_t region = NULL;
+ region = xbt_new0(s_mc_heap_ignore_region_t, 1);
+ region->address = address;
+ region->size = size;
+
+ region->block = ((char*)address - (char*)((xbt_mheap_t)std_heap)->heapbase) / BLOCKSIZE + 1;
+
+ if(((xbt_mheap_t)std_heap)->heapinfo[region->block].type == 0){
+ region->fragment = -1;
+ ((xbt_mheap_t)std_heap)->heapinfo[region->block].busy_block.ignore++;
+ }else{
+ region->fragment = ((uintptr_t) (ADDR2UINT (address) % (BLOCKSIZE))) >> ((xbt_mheap_t)std_heap)->heapinfo[region->block].type;
+ ((xbt_mheap_t)std_heap)->heapinfo[region->block].busy_frag.ignore[region->fragment]++;
+ }
+
+ if(mc_heap_comparison_ignore == NULL){
+ mc_heap_comparison_ignore = xbt_dynar_new(sizeof(mc_heap_ignore_region_t), heap_ignore_region_free_voidp);
+ xbt_dynar_push(mc_heap_comparison_ignore, ®ion);
+ if(!raw_mem_set)
+ MC_UNSET_RAW_MEM;
+ return;
+ }
+
+ unsigned int cursor = 0;
+ mc_heap_ignore_region_t current_region = NULL;
+ int start = 0;
+ int end = xbt_dynar_length(mc_heap_comparison_ignore) - 1;
+
+ while(start <= end){
+ cursor = (start + end) / 2;
+ current_region = (mc_heap_ignore_region_t)xbt_dynar_get_as(mc_heap_comparison_ignore, cursor, mc_heap_ignore_region_t);
+ if(current_region->address == address){
+ heap_ignore_region_free(region);
+ if(!raw_mem_set)
+ MC_UNSET_RAW_MEM;
+ return;
+ }else if(current_region->address < address){
+ start = cursor + 1;
+ }else{
+ end = cursor - 1;
+ }
+ }
+
+ if(current_region->address < address)
+ xbt_dynar_insert_at(mc_heap_comparison_ignore, cursor + 1, ®ion);
+ else
+ xbt_dynar_insert_at(mc_heap_comparison_ignore, cursor, ®ion);
+
+ if(!raw_mem_set)
+ MC_UNSET_RAW_MEM;
+}
+
+void MC_remove_ignore_heap(void *address, size_t size){
+
+ int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
+
+ MC_SET_RAW_MEM;
+
+ unsigned int cursor = 0;
+ int start = 0;
+ int end = xbt_dynar_length(mc_heap_comparison_ignore) - 1;
+ mc_heap_ignore_region_t region;
+ int ignore_found = 0;
+
+ while(start <= end){
+ cursor = (start + end) / 2;
+ region = (mc_heap_ignore_region_t)xbt_dynar_get_as(mc_heap_comparison_ignore, cursor, mc_heap_ignore_region_t);
+ if(region->address == address){
+ ignore_found = 1;
+ break;
+ }else if(region->address < address){
+ start = cursor + 1;
+ }else{
+ if((char * )region->address <= ((char *)address + size)){
+ ignore_found = 1;
+ break;
+ }else{
+ end = cursor - 1;
+ }
+ }
+ }
+
+ if(ignore_found == 1){
+ xbt_dynar_remove_at(mc_heap_comparison_ignore, cursor, NULL);
+ MC_remove_ignore_heap(address, size);
+ }
+
+ if(!raw_mem_set)
+ MC_UNSET_RAW_MEM;
+
+}
+
+void MC_ignore_global_variable(const char *name){
+
+ int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
+
+ MC_SET_RAW_MEM;
+
+ xbt_assert(mc_libsimgrid_info, "MC subsystem not initialized");
+
+ unsigned int cursor = 0;
+ dw_variable_t current_var;
+ int start = 0;
+ int end = xbt_dynar_length(mc_libsimgrid_info->global_variables) - 1;
+
+ while(start <= end){
+ cursor = (start + end) /2;
+ current_var = (dw_variable_t)xbt_dynar_get_as(mc_libsimgrid_info->global_variables, cursor, dw_variable_t);
+ if(strcmp(current_var->name, name) == 0){
+ xbt_dynar_remove_at(mc_libsimgrid_info->global_variables, cursor, NULL);
+ start = 0;
+ end = xbt_dynar_length(mc_libsimgrid_info->global_variables) - 1;
+ }else if(strcmp(current_var->name, name) < 0){
+ start = cursor + 1;
+ }else{
+ end = cursor - 1;
+ }
+ }
+
+ if(!raw_mem_set)
+ MC_UNSET_RAW_MEM;
+}
+
+void MC_ignore_local_variable(const char *var_name, const char *frame_name){
+
+ int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
+
+ 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;
+ }
+ }
+ }
+
+ if(!raw_mem_set)
+ MC_UNSET_RAW_MEM;
+
+}
+
+void MC_new_stack_area(void *stack, char *name, void* context, size_t size){
+
+ int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
+
+ MC_SET_RAW_MEM;
+
+ if(stacks_areas == NULL)
+ stacks_areas = xbt_dynar_new(sizeof(stack_region_t), NULL);
+
+ stack_region_t region = NULL;
+ region = xbt_new0(s_stack_region_t, 1);
+ region->address = stack;
+ region->process_name = strdup(name);
+ region->context = context;
+ region->size = size;
+ region->block = ((char*)stack - (char*)((xbt_mheap_t)std_heap)->heapbase) / BLOCKSIZE + 1;
+ xbt_dynar_push(stacks_areas, ®ion);
+
+ if(!raw_mem_set)
+ MC_UNSET_RAW_MEM;
+}
+
+void MC_ignore(void *addr, size_t size){
+
+ int raw_mem_set= (mmalloc_get_current_heap() == raw_heap);
+
+ MC_SET_RAW_MEM;
+
+ if(mc_checkpoint_ignore == NULL)
+ mc_checkpoint_ignore = xbt_dynar_new(sizeof(mc_checkpoint_ignore_region_t), checkpoint_ignore_region_free_voidp);
+
+ mc_checkpoint_ignore_region_t region = xbt_new0(s_mc_checkpoint_ignore_region_t, 1);
+ region->addr = addr;
+ region->size = size;
+
+ if(xbt_dynar_is_empty(mc_checkpoint_ignore)){
+ xbt_dynar_push(mc_checkpoint_ignore, ®ion);
+ }else{
+
+ unsigned int cursor = 0;
+ int start = 0;
+ int end = xbt_dynar_length(mc_checkpoint_ignore) -1;
+ mc_checkpoint_ignore_region_t current_region = NULL;
+
+ while(start <= end){
+ cursor = (start + end) / 2;
+ current_region = (mc_checkpoint_ignore_region_t)xbt_dynar_get_as(mc_checkpoint_ignore, cursor, mc_checkpoint_ignore_region_t);
+ if(current_region->addr == addr){
+ if(current_region->size == size){
+ checkpoint_ignore_region_free(region);
+ if(!raw_mem_set)
+ MC_UNSET_RAW_MEM;
+ return;
+ }else if(current_region->size < size){
+ start = cursor + 1;
+ }else{
+ end = cursor - 1;
+ }
+ }else if(current_region->addr < addr){
+ start = cursor + 1;
+ }else{
+ end = cursor - 1;
+ }
+ }
+
+ if(current_region->addr == addr){
+ if(current_region->size < size){
+ xbt_dynar_insert_at(mc_checkpoint_ignore, cursor + 1, ®ion);
+ }else{
+ xbt_dynar_insert_at(mc_checkpoint_ignore, cursor, ®ion);
+ }
+ }else if(current_region->addr < addr){
+ xbt_dynar_insert_at(mc_checkpoint_ignore, cursor + 1, ®ion);
+ }else{
+ xbt_dynar_insert_at(mc_checkpoint_ignore, cursor, ®ion);
+ }
+ }
+
+ if(!raw_mem_set)
+ MC_UNSET_RAW_MEM;
+}
+
+/******************************* Initialisation of MC *******************************/
+/*********************************************************************************/
+
+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, 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 !");
+}
+
+void MC_init(){
+
+ int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
+
+ compare = 0;
+
+ /* Initialize the data structures that must be persistent across every
+ iteration of the model-checker (in RAW memory) */
+
+ MC_SET_RAW_MEM;
+
+ MC_init_memory_map_info();
+ MC_init_debug_info();
+
+ /* Init parmap */
+ parmap = xbt_parmap_mc_new(xbt_os_get_numcores(), XBT_PARMAP_DEFAULT);
+
+ MC_UNSET_RAW_MEM;
+
+ /* Ignore some variables from xbt/ex.h used by exception e for stacks comparison */
+ MC_ignore_local_variable("e", "*");
+ MC_ignore_local_variable("__ex_cleanup", "*");
+ MC_ignore_local_variable("__ex_mctx_en", "*");
+ MC_ignore_local_variable("__ex_mctx_me", "*");
+ MC_ignore_local_variable("__xbt_ex_ctx_ptr", "*");
+ MC_ignore_local_variable("_log_ev", "*");
+ MC_ignore_local_variable("_throw_ctx", "*");
+ MC_ignore_local_variable("ctx", "*");
+
+ 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("mc_comp_times");
+ MC_ignore_global_variable("mc_snapshot_comparison_time");
+ MC_ignore_global_variable("mc_time");
+ MC_ignore_global_variable("smpi_current_rank");
+ MC_ignore_global_variable("counter"); /* Static variable used for tracing */
+ MC_ignore_global_variable("maestro_stack_start");
+ MC_ignore_global_variable("maestro_stack_end");
+ MC_ignore_global_variable("smx_total_comms");
+
+ MC_ignore_heap(&(simix_global->process_to_run), sizeof(simix_global->process_to_run));
+ MC_ignore_heap(&(simix_global->process_that_ran), sizeof(simix_global->process_that_ran));
+ MC_ignore_heap(simix_global->process_to_run, sizeof(*(simix_global->process_to_run)));
+ MC_ignore_heap(simix_global->process_that_ran, sizeof(*(simix_global->process_that_ran)));
+
+ smx_process_t process;
+ xbt_swag_foreach(process, simix_global->process_list){
+ MC_ignore_heap(&(process->process_hookup), sizeof(process->process_hookup));
+ }
+
+ if(raw_mem_set)
+ MC_SET_RAW_MEM;
+
+}
+
+static void MC_init_dot_output(){ /* FIXME : more colors */
+
+ colors[0] = "blue";
+ colors[1] = "red";
+ colors[2] = "green3";
+ colors[3] = "goldenrod";
+ colors[4] = "brown";
+ colors[5] = "purple";
+ colors[6] = "magenta";
+ colors[7] = "turquoise4";
+ colors[8] = "gray25";
+ colors[9] = "forestgreen";
+ colors[10] = "hotpink";
+ colors[11] = "lightblue";
+ colors[12] = "tan";
+
+ dot_output = fopen(_sg_mc_dot_output_file, "w");
+
+ if(dot_output == NULL){
+ perror("Error open dot output file");
+ xbt_abort();
+ }
+
+ fprintf(dot_output, "digraph graphname{\n fixedsize=true; rankdir=TB; ranksep=.25; edge [fontsize=12]; node [fontsize=10, shape=circle,width=.5 ]; graph [resolution=20, fontsize=10];\n");
+
+}
+
+/******************************* Core of MC *******************************/
+/**************************************************************************/