+static int compare_areas_with_type(void *area1, void *area2, mc_object_info_t info, mc_object_info_t other_info, dw_type_t type, int region_size, int region_type, void *start_data, int pointer_level){
+
+ unsigned int cursor = 0;
+ dw_type_t member, subtype, subsubtype;
+ int elm_size, i, res, switch_types = 0;
+ void *addr_pointed1, *addr_pointed2;
+
+ switch(type->type){
+ case DW_TAG_base_type:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_union_type:
+ return (memcmp(area1, area2, type->byte_size) != 0);
+ break;
+ case DW_TAG_typedef:
+ case DW_TAG_volatile_type:
+ case DW_TAG_const_type:
+ return compare_areas_with_type(area1, area2, info, other_info, type->subtype, region_size, region_type, start_data, pointer_level);
+ break;
+ case DW_TAG_array_type:
+ subtype = type->subtype;
+ switch(subtype->type){
+ case DW_TAG_base_type:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_pointer_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ if(subtype->byte_size == 0){ /*declaration of the type, need the complete description */
+ subtype = xbt_dict_get_or_null(other_info->types_by_name, subtype->name);
+ switch_types = 1;
+ }
+ elm_size = subtype->byte_size;
+ break;
+ case DW_TAG_const_type:
+ case DW_TAG_typedef:
+ case DW_TAG_volatile_type:
+ subsubtype = subtype->subtype;
+ if(subsubtype->byte_size == 0){ /*declaration of the type, need the complete description */
+ subsubtype = xbt_dict_get_or_null(other_info->types_by_name, subsubtype->name);
+ switch_types = 1;
+ }
+ elm_size = subsubtype->byte_size;
+ break;
+ default :
+ return 0;
+ break;
+ }
+ for(i=0; i<type->element_count; i++){
+ if(switch_types)
+ res = compare_areas_with_type((char *)area1 + (i*elm_size), (char *)area2 + (i*elm_size), other_info, info, type->subtype, region_size, region_type, start_data, pointer_level);
+ else
+ res = compare_areas_with_type((char *)area1 + (i*elm_size), (char *)area2 + (i*elm_size), info, other_info, type->subtype, region_size, region_type, start_data, pointer_level);
+ if(res == 1)
+ return res;
+ }
+ break;
+ case DW_TAG_pointer_type:
+ if(type->dw_type_id && ((dw_type_t)xbt_dict_get_or_null(info->types, type->dw_type_id))->type == DW_TAG_subroutine_type){
+ addr_pointed1 = *((void **)(area1));
+ addr_pointed2 = *((void **)(area2));
+ return (addr_pointed1 != addr_pointed2);
+ }else{
+ addr_pointed1 = *((void **)(area1));
+ addr_pointed2 = *((void **)(area2));
+
+ if(addr_pointed1 == NULL && addr_pointed2 == NULL)
+ return 0;
+ if(already_compared_pointers(addr_pointed1, addr_pointed2) != -1)
+ return 0;
+ add_compared_pointers(addr_pointed1, addr_pointed2);
+
+ pointer_level++;
+
+ // Some cases are not handled here:
+ // * the pointers lead to different areas (one to the heap, the other to the RW segment ...);
+ // * a pointer leads to the read-only segment of the current object;
+ // * a pointer lead to a different ELF object.
+
+ // The pointers are both in the heap:
+ if(addr_pointed1 > std_heap && (char *)addr_pointed1 < (char*) std_heap + STD_HEAP_SIZE){
+ if(!(addr_pointed2 > std_heap && (char *)addr_pointed2 < (char*) std_heap + STD_HEAP_SIZE))
+ return 1;
+ return compare_heap_area(addr_pointed1, addr_pointed2, NULL, info, other_info, type->dw_type_id, pointer_level);
+ }
+
+ // The pointers are both in the current object R/W segment:
+ else if(addr_pointed1 > start_data && (char*)addr_pointed1 <= (char *)start_data + region_size){
+ if(!(addr_pointed2 > start_data && (char*)addr_pointed2 <= (char *)start_data + region_size))
+ return 1;
+ if(type->dw_type_id == NULL)
+ return (addr_pointed1 != addr_pointed2);
+ else
+ return compare_areas_with_type(addr_pointed1, addr_pointed2, info, other_info, type->subtype, region_size, region_type, start_data, pointer_level);
+ }
+
+ else{
+ return (addr_pointed1 != addr_pointed2);