From: Gabriel Corona Date: Mon, 24 Feb 2014 09:04:38 +0000 (+0100) Subject: Merge 'master' into mc X-Git-Tag: v3_11~199^2~2^2~23 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/45c3f1cfee86fb48c96d53f8267f99b6db6e3d7a?hp=c7d7dd424bfef179ba41ff0461450f2f231e7125 Merge 'master' into mc Conflicts: src/mc/mc_checkpoint.c src/mc/mc_global.c src/mc/mc_private.h --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 83eb99b4d7..cfae0bbc05 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ if(WIN32) SET(CMAKE_RC_COMPILER "windres") endif() project(SimGrid C) -if (enable_gtnets OR enable_ns3) +if (enable_gtnets OR enable_ns3 OR enable_model-checking) enable_language(CXX) endif() diff --git a/buildtools/Cmake/CompleteInFiles.cmake b/buildtools/Cmake/CompleteInFiles.cmake index 04a2a3ef9a..98cc4617c8 100644 --- a/buildtools/Cmake/CompleteInFiles.cmake +++ b/buildtools/Cmake/CompleteInFiles.cmake @@ -225,6 +225,7 @@ if(enable_model-checking AND HAVE_MMALLOC) SET(HAVE_MC 1) SET(MMALLOC_WANT_OVERRIDE_LEGACY 1) include(FindLibunwind) + include(FindLibdw) else() if(enable_model-checking) message(STATUS "Warning: support for model-checking has been disabled because HAVE_MMALLOC is false") diff --git a/buildtools/Cmake/DefinePackages.cmake b/buildtools/Cmake/DefinePackages.cmake index b2d079e437..622d35ff12 100644 --- a/buildtools/Cmake/DefinePackages.cmake +++ b/buildtools/Cmake/DefinePackages.cmake @@ -542,6 +542,7 @@ set(MC_SRC src/mc/mc_compare.c src/mc/mc_dpor.c src/mc/mc_global.c + src/mc/mc_dwarf.c src/mc/mc_liveness.c src/mc/mc_memory.c src/mc/mc_private.h @@ -549,6 +550,8 @@ set(MC_SRC src/mc/mc_state.c src/mc/memory_map.c src/mc/mc_pair.c + src/mc/mc_hash.c + src/mc/mc_set.cpp ) set(headers_to_install @@ -1007,6 +1010,7 @@ set(CMAKE_SOURCE_FILES buildtools/Cmake/Modules/FindGraphviz.cmake buildtools/Cmake/Modules/FindLibSigc++.cmake buildtools/Cmake/Modules/FindLibunwind.cmake + buildtools/Cmake/Modules/FindLibdw.cmake buildtools/Cmake/Modules/FindLua51Simgrid.cmake buildtools/Cmake/Modules/FindNS3.cmake buildtools/Cmake/Modules/FindRngStream.cmake diff --git a/buildtools/Cmake/MakeLib.cmake b/buildtools/Cmake/MakeLib.cmake index 1e2113774d..25fdfad4b9 100644 --- a/buildtools/Cmake/MakeLib.cmake +++ b/buildtools/Cmake/MakeLib.cmake @@ -77,6 +77,9 @@ if(HAVE_MC) # (that includes FindLibunwind.cmake), so simply load it now. SET(SIMGRID_DEP "${SIMGRID_DEP} -lunwind") + + # Same for libdw + SET(SIMGRID_DEP "${SIMGRID_DEP} -ldw") # This supposes that the host machine is either an AMD or a X86. # This is deeply wrong, and should be fixed by manually loading -lunwind-PLAT (FIXME) if(PROCESSOR_x86_64) diff --git a/buildtools/Cmake/Modules/FindLibdw.cmake b/buildtools/Cmake/Modules/FindLibdw.cmake new file mode 100644 index 0000000000..9e07a38ebb --- /dev/null +++ b/buildtools/Cmake/Modules/FindLibdw.cmake @@ -0,0 +1,55 @@ +find_library(PATH_LIBDW_LIB + NAMES dw + HINTS + $ENV{SIMGRID_LIBDW_LIBRARY_PATH} + $ENV{LD_LIBRARY_PATH} + $ENV{LIBDW_LIBRARY_PATH} + PATH_SUFFIXES lib/ GnuWin32/lib + PATHS + /opt + /opt/local + /opt/csw + /sw + /usr) + + +find_path(PATH_LIBDW_H "elfutils/libdw.h" + HINTS + $ENV{SIMGRID_LIBDW_LIBRARY_PATH} + $ENV{LD_LIBRARY_PATH} + $ENV{LIBDW_LIBRARY_PATH} + PATH_SUFFIXES include/ GnuWin32/include + PATHS + /opt + /opt/local + /opt/csw + /sw + /usr) + +message(STATUS "Looking for libdw.h") +if(PATH_LIBDW_H) + message(STATUS "Looking for libdw.h - found") +else() + message(STATUS "Looking for libdw.h - not found") +endif() + +message(STATUS "Looking for libdw") +if(PATH_LIBDW_LIB) + message(STATUS "Looking for libdw - found") +else() + message(STATUS "Looking for libdw - not found") +endif() + +if(PATH_LIBDW_LIB AND PATH_LIBDW_H) + string(REGEX REPLACE "/libdw.*[.]${LIB_EXE}$" "" PATH_LIBDW_LIB "${PATH_LIBDW_LIB}") + string(REGEX REPLACE "/libdw.h" "" PATH_LIBDW_H "${PATH_LIBDW_H}") + + include_directories(${PATH_LIBDW_H}) + link_directories(${PATH_LIBDW_LIB}) + +else() + message(FATAL_ERROR "Please either install the libdw-dev package (or equivalent) or turn off the model-checking option of SimGrid.") +endif() + +mark_as_advanced(PATH_LIBDW_H) +mark_as_advanced(PATH_LIBDW_LIB) diff --git a/buildtools/Cmake/Modules/FindLibunwind.cmake b/buildtools/Cmake/Modules/FindLibunwind.cmake index 56de1f79a0..03bbed91de 100644 --- a/buildtools/Cmake/Modules/FindLibunwind.cmake +++ b/buildtools/Cmake/Modules/FindLibunwind.cmake @@ -66,5 +66,5 @@ else() message(FATAL_ERROR "Please either install the libunwind7-dev package (or equivalent) or turn off the model-checking option of SimGrid.") endif() -mark_as_advanced(PATH_LIBUNWIND_H) -mark_as_advanced(PATH_LIBUNWIND_LIB) \ No newline at end of file +mark_as_advanced(PATH_LIBDW_H) +mark_as_advanced(PATH_LIBDW_LIB) diff --git a/examples/msg/mc/bugged1.tesh b/examples/msg/mc/bugged1.tesh index 464633f5a9..bcebdf8c9d 100644 --- a/examples/msg/mc/bugged1.tesh +++ b/examples/msg/mc/bugged1.tesh @@ -5,6 +5,8 @@ $ ${bindir:=.}/bugged1 --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" > [ 0.000000] (0:@) Configuration change: Set 'model-check' to '1' > [ 0.000000] (0:@) Check a safety property +> [ 0.000000] (0:@) Get debug information ... +> [ 0.000000] (0:@) Get debug information done ! > [ 0.000000] (2:client@HostB) Sent! > [ 0.000000] (3:client@HostC) Sent! > [ 0.000000] (1:server@HostA) OK diff --git a/examples/msg/mc/bugged2.tesh b/examples/msg/mc/bugged2.tesh index 2fe18e9581..df06aafaaf 100644 --- a/examples/msg/mc/bugged2.tesh +++ b/examples/msg/mc/bugged2.tesh @@ -5,6 +5,8 @@ $ ${bindir:=.}/bugged2 --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n" > [ 0.000000] (0:@) Configuration change: Set 'model-check' to '1' > [ 0.000000] (0:@) Check a safety property +> [ 0.000000] (0:@) Get debug information ... +> [ 0.000000] (0:@) Get debug information done ! > [ 0.000000] (2:client@HostB) Send 1! > [ 0.000000] (3:client@HostC) Send 2! > [ 0.000000] (1:server@HostA) Received 1 diff --git a/generate.sh b/generate.sh new file mode 100755 index 0000000000..5f39fdd2ac --- /dev/null +++ b/generate.sh @@ -0,0 +1,5 @@ +#!/bin/sh +# Generate files from a given dwarf.h + +cat "$1" | grep DW_TAG_ | sed 's/.*\(DW_TAG_[^ ]*\) = \(0x[0-9a-f]*\).*/case \2: return "\1";/' > src/mc/mc_dwarf_tagnames.h +cat "$1" | grep DW_AT_ | sed 's/.*\(DW_AT_[^ ]*\) = \(0x[0-9a-f]*\).*/case \2: return "\1";/' > src/mc/mc_dwarf_attrnames.h diff --git a/include/smpi/mpi.h b/include/smpi/mpi.h index 28309832ac..4224e7ffbc 100644 --- a/include/smpi/mpi.h +++ b/include/smpi/mpi.h @@ -16,5 +16,11 @@ #include #include #include +#include + +#ifdef HAVE_MC +#undef assert +#define assert(x) MC_assert(x) +#endif #endif diff --git a/include/xbt/mmalloc.h b/include/xbt/mmalloc.h index d583884d3f..dc3a51c864 100644 --- a/include/xbt/mmalloc.h +++ b/include/xbt/mmalloc.h @@ -19,6 +19,7 @@ #include "xbt/dynar.h" #include "xbt/dict.h" +#include "mc/datatypes.h" /* Datatype representing a separate heap. The whole point of the mmalloc module * is to allow several such heaps in the process. It thus works by redefining @@ -37,6 +38,7 @@ void *mmalloc_no_memset(xbt_mheap_t mdp, size_t size); /* Re-allocate the previously allocated block in void*, making the new block SIZE bytes long. */ + XBT_PUBLIC( void ) *mrealloc(xbt_mheap_t md, void *ptr, size_t size); /* Free a block allocated by `mmalloc', `mrealloc' or `mcalloc'. */ @@ -55,12 +57,11 @@ XBT_PUBLIC( xbt_mheap_t ) mmalloc_get_default_md(void); void mmalloc_set_current_heap(xbt_mheap_t new_heap); xbt_mheap_t mmalloc_get_current_heap(void); -int mmalloc_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dict_t all_types, xbt_dict_t other_types); +int mmalloc_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2, mc_object_info_t info, mc_object_info_t other_info); int mmalloc_linear_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2); int init_heap_information(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dynar_t to_ignore1, xbt_dynar_t to_ignore2); -int compare_heap_area(void *area1, void* area2, xbt_dynar_t previous, xbt_dict_t all_types, xbt_dict_t other_types, char *type, int pointer_level); +int compare_heap_area(void *area1, void* area2, xbt_dynar_t previous, mc_object_info_t info, mc_object_info_t other_info, char *type, int pointer_level); void reset_heap_information(void); -int get_pointed_area_size(void *area, int heap); size_t mmalloc_get_bytes_used(xbt_mheap_t); ssize_t mmalloc_get_busy_size(xbt_mheap_t, void *ptr); diff --git a/src/include/mc/datatypes.h b/src/include/mc/datatypes.h index 2cc5834761..9cdea6cc82 100644 --- a/src/include/mc/datatypes.h +++ b/src/include/mc/datatypes.h @@ -6,10 +6,16 @@ #ifndef MC_DATATYPE_H #define MC_DATATYPE_H + +#define UNW_LOCAL_ONLY + #include "xbt/misc.h" #include "xbt/swag.h" #include "xbt/fifo.h" +#include +#include + SG_BEGIN_DECL() /******************************* Transitions **********************************/ @@ -37,34 +43,31 @@ typedef struct s_stack_region{ void heap_ignore_region_free(mc_heap_ignore_region_t r); void heap_ignore_region_free_voidp(void *r); +/************ Object info *************/ + +typedef struct s_mc_object_info s_mc_object_info_t, *mc_object_info_t; + /************ DWARF structures *************/ -typedef enum{ - e_dw_base_type = 0, - e_dw_enumeration_type, - e_dw_enumerator, - e_dw_typedef, - e_dw_const_type, - e_dw_array_type, - e_dw_pointer_type, - e_dw_structure_type, - e_dw_union_type, - e_dw_subroutine_type, - e_dw_volatile_type -}e_dw_type_type; - -typedef struct s_dw_type{ +typedef int e_dw_type_type; + +typedef struct s_dw_type s_dw_type_t, *dw_type_t; + +struct s_dw_type{ e_dw_type_type type; - void *id; - char *name; - int size; - char *dw_type_id; - xbt_dynar_t members; /* if DW_TAG_structure_type */ + void *id; /* Offset in the section (in hexadecimal form) */ + char *name; /* Name of the type */ + int byte_size; /* Size in bytes */ + int element_count; /* Number of elements for array type */ + char *dw_type_id; /* DW_AT_type */ + xbt_dynar_t members; /* if DW_TAG_structure_type, DW_TAG_union_type*/ int is_pointer_type; int offset; -}s_dw_type_t, *dw_type_t; + dw_type_t subtype; + dw_type_t other_object_same_type; // The same (but more complete) type in the other object. +}; -char* get_type_description(xbt_dict_t types, char *type_name); +char* get_type_description(mc_object_info_t info, char *type_name); SG_END_DECL() #endif /* _MC_MC_H */ diff --git a/src/include/mc/mc.h b/src/include/mc/mc.h index 494b6516cd..d00a13d580 100644 --- a/src/include/mc/mc.h +++ b/src/include/mc/mc.h @@ -26,9 +26,11 @@ extern int _sg_do_model_check; extern int _sg_mc_checkpoint; extern char* _sg_mc_property_file; extern int _sg_mc_timeout; +extern int _sg_mc_hash; extern int _sg_mc_max_depth; extern int _sg_mc_visited; extern char* _sg_mc_dot_output_file; +extern int _sg_mc_comms_determinism; extern xbt_dynar_t mc_heap_comparison_ignore; extern xbt_dynar_t stacks_areas; @@ -40,9 +42,11 @@ void _mc_cfg_cb_reduce(const char *name, int pos); void _mc_cfg_cb_checkpoint(const char *name, int pos); void _mc_cfg_cb_property(const char *name, int pos); void _mc_cfg_cb_timeout(const char *name, int pos); +void _mc_cfg_cb_hash(const char *name, int pos); void _mc_cfg_cb_max_depth(const char *name, int pos); void _mc_cfg_cb_visited(const char *name, int pos); void _mc_cfg_cb_dot_output(const char *name, int pos); +void _mc_cfg_cb_comms_determinism(const char *name, int pos); XBT_PUBLIC(void) MC_do_the_modelcheck_for_real(void); diff --git a/src/mc/mc_checkpoint.c b/src/mc/mc_checkpoint.c index 39e743a2ef..d534d891d7 100644 --- a/src/mc/mc_checkpoint.c +++ b/src/mc/mc_checkpoint.c @@ -4,26 +4,28 @@ /* This program is free software; you can redistribute it and/or modify it * under the terms of the license (GNU LGPL) which comes with this package. */ -#include +#define _GNU_SOURCE +#define UNW_LOCAL_ONLY + +#include +#include #include "mc_private.h" #include "xbt/module.h" +#include + +#include "xbt/mmalloc/mmprivate.h" #include "../simix/smx_private.h" #include +#include + +#include "mc_private.h" XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_checkpoint, mc, "Logging specific to mc_checkpoint"); -void *start_text_libsimgrid; -void *start_plt_libsimgrid, *end_plt_libsimgrid; -void *start_got_plt_libsimgrid, *end_got_plt_libsimgrid; -void *start_plt_binary, *end_plt_binary; -void *start_got_plt_binary, *end_got_plt_binary; char *libsimgrid_path; -void *start_data_libsimgrid, *start_bss_libsimgrid; -void *start_data_binary, *start_bss_binary; -void *start_text_binary; /************************************ Free functions **************************************/ /*****************************************************************************************/ @@ -31,6 +33,7 @@ void *start_text_binary; static void MC_snapshot_stack_free(mc_snapshot_stack_t s){ if(s){ xbt_dynar_free(&(s->local_variables)); + xbt_dynar_free(&(s->stack_frames)); xbt_free(s); } } @@ -42,7 +45,6 @@ static void MC_snapshot_stack_free_voidp(void *s){ static void local_variable_free(local_variable_t v){ xbt_free(v->frame); xbt_free(v->name); - xbt_free(v->type); xbt_free(v); } @@ -73,10 +75,10 @@ void MC_free_snapshot(mc_snapshot_t snapshot){ static mc_mem_region_t MC_region_new(int type, void *start_addr, size_t size) { - mc_mem_region_t new_reg = xbt_new0(s_mc_mem_region_t, 1); + mc_mem_region_t new_reg = xbt_new(s_mc_mem_region_t, 1); new_reg->start_addr = start_addr; new_reg->size = size; - new_reg->data = xbt_malloc0(size); + new_reg->data = xbt_malloc(size); memcpy(new_reg->data, start_addr, size); XBT_DEBUG("New region : type : %d, data : %p (real addr %p), size : %zu", type, new_reg->data, start_addr, size); @@ -102,561 +104,235 @@ static void MC_snapshot_add_region(mc_snapshot_t snapshot, int type, void *start static void MC_get_memory_regions(mc_snapshot_t snapshot){ - FILE *fp; - char *line = NULL; - ssize_t read; - size_t n = 0; - - char *lfields[6] = {0}, *tok; - void *start_addr, *start_addr1, *end_addr; - size_t size; - int i; - - fp = fopen("/proc/self/maps", "r"); - - xbt_assert(fp, - "Cannot open /proc/self/maps to investigate the memory map of the process. Please report this bug."); - - setbuf(fp, NULL); - - while((read = xbt_getline(&line, &n, fp)) != -1){ - - /* Wipeout the new line character */ - line[read - 1] = '\0'; - - /* Tokenize the line using spaces as delimiters and store each token */ - lfields[0] = strtok(line, " "); - - for (i = 1; i < 6 && lfields[i - 1] != NULL; i++) { - lfields[i] = strtok(NULL, " "); - } - - /* First get the permissions flags, need write permission */ - if(lfields[1][1] == 'w'){ - - /* Get the start address of the map */ - tok = strtok(lfields[0], "-"); - start_addr = (void *)strtoul(tok, NULL, 16); - - if(start_addr == std_heap){ /* Std_heap ? */ - tok = strtok(NULL, "-"); - end_addr = (void *)strtoul(tok, NULL, 16); - MC_snapshot_add_region(snapshot, 0, start_addr, (char*)end_addr - (char*)start_addr); - snapshot->heap_bytes_used = mmalloc_get_bytes_used(std_heap); - }else{ /* map name == libsimgrid || binary_name ? */ - if(lfields[5] != NULL){ - if(!memcmp(basename(lfields[5]), "libsimgrid", 10)){ - tok = strtok(NULL, "-"); - end_addr = (void *)strtoul(tok, NULL, 16); - size = (char*)end_addr - (char*)start_addr; - /* BSS and data segments may be separated according to the OS */ - if((read = xbt_getline(&line, &n, fp)) != -1){ - line[read - 1] = '\0'; - lfields[0] = strtok(line, " "); - for (i = 1; i < 6 && lfields[i - 1] != NULL; i++) { - lfields[i] = strtok(NULL, " "); - } - if(lfields[1][1] == 'w' && lfields[5] == NULL){ - tok = strtok(lfields[0], "-"); - start_addr1 = (void *)strtoul(tok, NULL, 16); - tok = strtok(NULL, "-"); - size += (char *)(void *)strtoul(tok, NULL, 16) - (char*)start_addr1; - } - } - MC_snapshot_add_region(snapshot, 1, start_addr, size); - }else if(!memcmp(basename(lfields[5]), basename(xbt_binary_name), strlen(basename(xbt_binary_name)))){ - tok = strtok(NULL, "-"); - end_addr = (void *)strtoul(tok, NULL, 16); - size = (char*)end_addr - (char*)start_addr; - /* BSS and data segments may be separated according to the OS */ - if((read = xbt_getline(&line, &n, fp)) != -1){ - line[read - 1] = '\0'; - lfields[0] = strtok(line, " "); - for (i = 1; i < 6 && lfields[i - 1] != NULL; i++) { - lfields[i] = strtok(NULL, " "); - } - tok = strtok(lfields[0], "-"); - start_addr1 = (void *)strtoul(tok, NULL, 16); - if(lfields[1][1] == 'w' && lfields[5] == NULL){ - if(start_addr1 == std_heap){ /* Std_heap ? */ - tok = strtok(NULL, "-"); - end_addr = (void *)strtoul(tok, NULL, 16); - MC_snapshot_add_region(snapshot, 0, start_addr1, (char*)end_addr - (char*)start_addr1); - snapshot->heap_bytes_used = mmalloc_get_bytes_used(std_heap); - }else if(start_addr1 != raw_heap){ - tok = strtok(NULL, "-"); - size += (char *)(void *)strtoul(tok, NULL, 16) - (char *)start_addr1; - } - } - } - MC_snapshot_add_region(snapshot, 2, start_addr, size); - }else if (!memcmp(lfields[5], "[stack]", 7)){ - maestro_stack_start = start_addr; - tok = strtok(NULL, "-"); - maestro_stack_end = (void *)strtoul(tok, NULL, 16); - } - } - } - } - - } - - free(line); - fclose(fp); + void* start_heap = ((xbt_mheap_t)std_heap)->base; + void* end_heap = ((xbt_mheap_t)std_heap)->breakval; + MC_snapshot_add_region(snapshot, 0, start_heap, (char*) end_heap - (char*) start_heap); + snapshot->heap_bytes_used = mmalloc_get_bytes_used(std_heap); + MC_snapshot_add_region(snapshot, 1, mc_libsimgrid_info->start_rw, mc_libsimgrid_info->end_rw - mc_libsimgrid_info->start_rw); + MC_snapshot_add_region(snapshot, 2, mc_binary_info->start_rw, mc_binary_info->end_rw - mc_binary_info->start_rw); } +/** @brief Finds the range of the different memory segments and binary paths */ void MC_init_memory_map_info(){ unsigned int i = 0; s_map_region_t reg; memory_map_t maps = MC_get_memory_map(); + maestro_stack_start = NULL; + maestro_stack_end = NULL; + libsimgrid_path = NULL; + while (i < maps->mapsize) { reg = maps->regions[i]; - if ((reg.prot & PROT_WRITE)){ - if (maps->regions[i].pathname != NULL){ - if (!memcmp(basename(maps->regions[i].pathname), "libsimgrid", 10)){ - start_data_libsimgrid = reg.start_addr; - i++; - reg = maps->regions[i]; - if(reg.pathname == NULL && (reg.prot & PROT_WRITE) && i < maps->mapsize) - start_bss_libsimgrid = reg.start_addr; - }else if (!memcmp(basename(maps->regions[i].pathname), basename(xbt_binary_name), strlen(basename(xbt_binary_name)))){ - start_data_binary = reg.start_addr; - i++; - reg = maps->regions[i]; - if(reg.pathname == NULL && (reg.prot & PROT_WRITE) && reg.start_addr != std_heap && reg.start_addr != raw_heap && i < maps->mapsize){ - start_bss_binary = reg.start_addr; - i++; - } - }else if(!memcmp(maps->regions[i].pathname, "[stack]", 7)){ + if (maps->regions[i].pathname == NULL) { + // Nothing to do + } + else if ((reg.prot & PROT_WRITE) && !memcmp(maps->regions[i].pathname, "[stack]", 7)){ maestro_stack_start = reg.start_addr; maestro_stack_end = reg.end_addr; - i++; - } - } - }else if ((reg.prot & PROT_READ) && (reg.prot & PROT_EXEC)){ - if (maps->regions[i].pathname != NULL){ - if (!memcmp(basename(maps->regions[i].pathname), "libsimgrid", 10)){ - start_text_libsimgrid = reg.start_addr; + } else if ((reg.prot & PROT_READ) && (reg.prot & PROT_EXEC) && !memcmp(basename(maps->regions[i].pathname), "libsimgrid", 10)){ + if(libsimgrid_path == NULL) libsimgrid_path = strdup(maps->regions[i].pathname); - }else if (!memcmp(basename(maps->regions[i].pathname), basename(xbt_binary_name), strlen(basename(xbt_binary_name)))){ - start_text_binary = reg.start_addr; - } - } } i++; } - - MC_free_memory_map(maps); - -} - -void MC_get_libsimgrid_plt_section(){ - FILE *fp; - char *line = NULL; /* Temporal storage for each line that is readed */ - ssize_t read; /* Number of bytes readed */ - size_t n = 0; /* Amount of bytes to read by xbt_getline */ + xbt_assert(maestro_stack_start, "maestro_stack_start"); + xbt_assert(maestro_stack_end, "maestro_stack_end"); + xbt_assert(libsimgrid_path, "libsimgrid_path&"); - char *lfields[7]; - int i, plt_found = 0; - unsigned long int size, offset; - - char *command = bprintf("objdump --section-headers %s", libsimgrid_path); + MC_free_memory_map(maps); - fp = popen(command, "r"); +} - if(fp == NULL){ - perror("popen failed"); - xbt_abort(); +/** \brief Fill/llokup the "subtype" field. + */ +static void MC_resolve_subtype(mc_object_info_t info, dw_type_t type) { + + if(type->dw_type_id==NULL) + return; + type->subtype = xbt_dict_get_or_null(info->types, type->dw_type_id); + if(type->subtype==NULL) + return; + if(type->subtype->byte_size != 0) + return; + if(type->subtype->name==NULL) + return; + // Try to find a more complete description of the type: + // We need to fix in order to support C++. + + dw_type_t subtype = xbt_dict_get_or_null(info->types_by_name, type->subtype->name); + if(subtype!=NULL) { + type->subtype = subtype; } - while ((read = xbt_getline(&line, &n, fp)) != -1 && plt_found != 2) { - - if(n == 0) - continue; - - /* Wipeout the new line character */ - line[read - 1] = '\0'; - - lfields[0] = strtok(line, " "); - - if(lfields[0] == NULL) - continue; - - if(strcmp(lfields[0], "Sections:") == 0 || strcmp(lfields[0], "Idx") == 0 || strncmp(lfields[0], libsimgrid_path, strlen(libsimgrid_path)) == 0) - continue; + // TODO, support "switch type" (looking up the type in another lib) when possible +} - for (i = 1; i < 7 && lfields[i - 1] != NULL; i++) { - lfields[i] = strtok(NULL, " "); - } +void MC_post_process_types(mc_object_info_t info) { + xbt_dict_cursor_t cursor = NULL; + char *origin; + dw_type_t type; - if(i>=6){ - if(strcmp(lfields[1], ".plt") == 0){ - size = strtoul(lfields[2], NULL, 16); - offset = strtoul(lfields[5], NULL, 16); - start_plt_libsimgrid = (char *)start_text_libsimgrid + offset; - end_plt_libsimgrid = (char *)start_plt_libsimgrid + size; - plt_found++; - }else if(strcmp(lfields[1], ".got.plt") == 0){ - size = strtoul(lfields[2], NULL, 16); - offset = strtoul(lfields[5], NULL, 16); - start_got_plt_libsimgrid = (char *)start_text_libsimgrid + offset; - end_got_plt_libsimgrid = (char *)start_got_plt_libsimgrid + size; - plt_found++; - } + // Lookup "subtype" field: + xbt_dict_foreach(info->types, cursor, origin, type){ + MC_resolve_subtype(info, type); + dw_type_t member; + unsigned int i = 0; + if(type->members!=NULL) xbt_dynar_foreach(type->members, i, member) { + MC_resolve_subtype(info, member); } - } - - xbt_free(command); - xbt_free(line); - pclose(fp); - } -void MC_get_binary_plt_section(){ - - FILE *fp; - char *line = NULL; /* Temporal storage for each line that is readed */ - ssize_t read; /* Number of bytes readed */ - size_t n = 0; /* Amount of bytes to read by xbt_getline */ - - char *lfields[7]; - int i, plt_found = 0; - unsigned long int size; +/** \brief Fills the position of the .bss and .data sections. */ +void MC_find_object_address(memory_map_t maps, mc_object_info_t result) { - char *command = bprintf( "objdump --section-headers %s", xbt_binary_name); - - fp = popen(command, "r"); - - if(fp == NULL){ - perror("popen failed"); - xbt_abort(); - } - - while ((read = xbt_getline(&line, &n, fp)) != -1 && plt_found != 2) { - - if(n == 0) - continue; - - /* Wipeout the new line character */ - line[read - 1] = '\0'; - - lfields[0] = strtok(line, " "); - - if(lfields[0] == NULL) - continue; - - if(strcmp(lfields[0], "Sections:") == 0 || strcmp(lfields[0], "Idx") == 0 || strncmp(lfields[0], basename(xbt_binary_name), strlen(xbt_binary_name)) == 0) - continue; - - for (i = 1; i < 7 && lfields[i - 1] != NULL; i++) { - lfields[i] = strtok(NULL, " "); + unsigned int i = 0; + s_map_region_t reg; + const char* name = basename(result->file_name); + while (i < maps->mapsize) { + reg = maps->regions[i]; + if (maps->regions[i].pathname == NULL || strcmp(basename(maps->regions[i].pathname), name)) { + // Nothing to do } - - if(i>=6){ - if(strcmp(lfields[1], ".plt") == 0){ - size = strtoul(lfields[2], NULL, 16); - start_plt_binary = (void *)strtoul(lfields[3], NULL, 16); - end_plt_binary = (char *)start_plt_binary + size; - plt_found++; - }else if(strcmp(lfields[1], ".got.plt") == 0){ - size = strtoul(lfields[2], NULL, 16); - start_got_plt_binary = (char *)strtoul(lfields[3], NULL, 16); - end_got_plt_binary = (char *)start_got_plt_binary + size; - plt_found++; - } + else if ((reg.prot & PROT_WRITE)){ + xbt_assert(!result->start_rw, + "Multiple read-write segments for %s, not supported", + maps->regions[i].pathname); + result->start_rw = reg.start_addr; + result->end_rw = reg.end_addr; + // .bss is usually after the .data: + // TODO, use dl_iterate_phdr to be more robust + s_map_region_t* next = &(maps->regions[i+1]); + if(next->pathname == NULL && (next->prot & PROT_WRITE) && next->start_addr == reg.end_addr) { + result->end_rw = maps->regions[i+1].end_addr; + } + } else if ((reg.prot & PROT_READ) && (reg.prot & PROT_EXEC)){ + xbt_assert(!result->start_exec, + "Multiple executable segments for %s, not supported", + maps->regions[i].pathname); + result->start_exec = reg.start_addr; + result->end_exec = reg.end_addr; + } + else if((reg.prot & PROT_READ) && !(reg.prot & PROT_EXEC)) { + xbt_assert(!result->start_ro, + "Multiple read only segments for %s, not supported", + maps->regions[i].pathname); + result->start_ro = reg.start_addr; + result->end_ro = reg.end_addr; } - - + i++; } - xbt_free(command); - xbt_free(line); - pclose(fp); - + xbt_assert(result->file_name); + xbt_assert(result->start_rw); + xbt_assert(result->start_exec); } /************************************* Take Snapshot ************************************/ /****************************************************************************************/ -static void MC_get_hash_global(char *snapshot_hash, void *data1, void *data2){ - - /* unsigned int cursor = 0; */ - /* size_t offset; */ - /* global_variable_t current_var; */ - /* void *addr_pointed = NULL; */ - /* void *res = NULL; */ - - /* xbt_strbuff_t clear = xbt_strbuff_new(); */ - - /* xbt_dynar_foreach(mc_global_variables, cursor, current_var){ */ - /* if(current_var->address < start_data_libsimgrid){ /\* binary *\/ */ - /* offset = (char *)current_var->address - (char *)start_data_binary; */ - /* addr_pointed = *((void **)((char *)data2 + offset)); */ - /* if(((addr_pointed >= start_plt_binary && addr_pointed <= end_plt_binary)) || ((addr_pointed >= std_heap && (char *)addr_pointed <= (char *)std_heap + STD_HEAP_SIZE ))) */ - /* continue; */ - /* res = xbt_malloc0(current_var->size + 1); */ - /* memset(res, 0, current_var->size + 1); */ - /* memcpy(res, (char*)data2 + offset, current_var->size); */ - /* }else{ /\* libsimgrid *\/ */ - /* offset = (char *)current_var->address - (char *)start_data_libsimgrid; */ - /* addr_pointed = *((void **)((char *)data1 + offset)); */ - /* if((addr_pointed >= start_plt_libsimgrid && addr_pointed <= end_plt_libsimgrid) || (addr_pointed >= std_heap && (char *)addr_pointed <= (char *)std_heap + STD_HEAP_SIZE )) */ - /* continue; */ - /* res = xbt_malloc0(current_var->size + 1); */ - /* memset(res, 0, current_var->size + 1); */ - /* memcpy(res, (char*)data1 + offset, current_var->size); */ - /* } */ - /* if(res != NULL){ */ - /* xbt_strbuff_append(clear, (const char*)res); */ - /* xbt_free(res); */ - /* res = NULL; */ - /* } */ - /* } */ - - /* xbt_sha(clear->data, snapshot_hash); */ - - /* xbt_strbuff_free(clear); */ - -} - -static void MC_get_hash_local(char *snapshot_hash, xbt_dynar_t stacks){ - - /* xbt_dynar_t tokens = NULL, s_tokens = NULL; */ - /* unsigned int cursor1 = 0, cursor2 = 0; */ - /* mc_snapshot_stack_t current_stack; */ - /* char *frame_name = NULL; */ - /* void *addr; */ - - /* xbt_strbuff_t clear = xbt_strbuff_new(); */ - - /* while(cursor1 < xbt_dynar_length(stacks)){ */ - /* current_stack = xbt_dynar_get_as(stacks, cursor1, mc_snapshot_stack_t); */ - /* tokens = xbt_str_split(current_stack->local_variables->data, NULL); */ - /* cursor2 = 0; */ - /* while(cursor2 < xbt_dynar_length(tokens)){ */ - /* s_tokens = xbt_str_split(xbt_dynar_get_as(tokens, cursor2, char *), "="); */ - /* if(xbt_dynar_length(s_tokens) > 1){ */ - /* if(strcmp(xbt_dynar_get_as(s_tokens, 0, char *), "frame_name") == 0){ */ - /* xbt_free(frame_name); */ - /* frame_name = xbt_strdup(xbt_dynar_get_as(s_tokens, 1, char *)); */ - /* xbt_strbuff_append(clear, (const char*)xbt_dynar_get_as(tokens, cursor2, char *)); */ - /* cursor2++; */ - /* xbt_dynar_free(&s_tokens); */ - /* continue; */ - /* } */ - /* addr = (void *) strtoul(xbt_dynar_get_as(s_tokens, 1, char *), NULL, 16); */ - /* if(addr > std_heap && (char *)addr <= (char *)std_heap + STD_HEAP_SIZE){ */ - /* cursor2++; */ - /* xbt_dynar_free(&s_tokens); */ - /* continue; */ - /* } */ - /* if(is_stack_ignore_variable(frame_name, xbt_dynar_get_as(s_tokens, 0, char *))){ */ - /* cursor2++; */ - /* xbt_dynar_free(&s_tokens); */ - /* continue; */ - /* } */ - /* xbt_strbuff_append(clear, (const char *)xbt_dynar_get_as(tokens, cursor2, char *)); */ - /* } */ - /* xbt_dynar_free(&s_tokens); */ - /* cursor2++; */ - /* } */ - /* xbt_dynar_free(&tokens); */ - /* cursor1++; */ - /* } */ - - /* xbt_free(frame_name); */ - - /* xbt_sha(clear->data, snapshot_hash); */ - - /* xbt_strbuff_free(clear); */ - -} - -static xbt_dynar_t MC_get_local_variables_values(void *stack_context){ - - unw_cursor_t c; - int ret; - - char frame_name[256]; - - ret = unw_init_local(&c, (unw_context_t *)stack_context); - if(ret < 0){ - XBT_INFO("unw_init_local failed"); - xbt_abort(); - } - - unw_word_t ip, sp, off; - dw_frame_t frame; - - unsigned int cursor = 0; - dw_variable_t current_variable; - dw_location_entry_t entry = NULL; - dw_location_t location_entry = NULL; - unw_word_t res; - int frame_found = 0, region_type; - void *frame_pointer_address = NULL; - unsigned long true_ip, value; - int stop = 0; +static xbt_dynar_t MC_get_local_variables_values(xbt_dynar_t stack_frames){ + unsigned cursor1 = 0; + mc_stack_frame_t stack_frame; xbt_dynar_t variables = xbt_dynar_new(sizeof(local_variable_t), local_variable_free_voidp); - while(ret >= 0 && !stop){ - - unw_get_reg(&c, UNW_REG_IP, &ip); - unw_get_reg(&c, UNW_REG_SP, &sp); + xbt_dynar_foreach(stack_frames,cursor1,stack_frame) { - unw_get_proc_name(&c, frame_name, sizeof (frame_name), &off); - - if(!strcmp(frame_name, "smx_ctx_sysv_wrapper")) /* Stop before context switch with maestro */ - stop = 1; - - if((uintptr_t)ip > (uintptr_t)start_text_libsimgrid) - frame = xbt_dict_get_or_null(mc_local_variables_libsimgrid, frame_name); - else - frame = xbt_dict_get_or_null(mc_local_variables_binary, frame_name); - - if(frame == NULL){ - ret = unw_step(&c); - continue; - } - - true_ip = (unsigned long)frame->low_pc + (unsigned long)off; - frame_pointer_address = NULL; - - /* Get frame pointer */ - switch(frame->frame_base->type){ - case e_dw_loclist: - cursor = 0; - while(cursor < xbt_dynar_length(frame->frame_base->location.loclist) && !frame_found){ - entry = xbt_dynar_get_as(frame->frame_base->location.loclist, cursor, dw_location_entry_t); - if((true_ip >= entry->lowpc) && (true_ip < entry->highpc)){ - frame_found = 1; - switch(entry->location->type){ - case e_dw_compose: - if(xbt_dynar_length(entry->location->location.compose) > 1){ - frame_pointer_address = NULL; /* TODO : location list with optimizations enabled */ - }else{ - location_entry = xbt_dynar_get_as(entry->location->location.compose, 0, dw_location_t); - switch(location_entry->type){ - case e_dw_register: - unw_get_reg(&c, location_entry->location.reg, &res); - frame_pointer_address = (void*)(uintptr_t)res; - break; - case e_dw_bregister_op: - unw_get_reg(&c, location_entry->location.breg_op.reg, &res); - frame_pointer_address = (void*)((uintptr_t)res + location_entry->location.breg_op.offset); - break; - default: - frame_pointer_address = NULL; /* FIXME : implement other cases (with optimizations enabled) */ - break; - } - } - break; - default: - frame_pointer_address = NULL; /* FIXME : implement other cases (with optimizations enabled) */ - break; - } - } - cursor++; - } - break; - default : - frame_pointer_address = NULL; /* FIXME : implement other cases (with optimizations enabled)*/ - break; - } - - frame_found = 0; - cursor = 0; - - xbt_dynar_foreach(frame->variables, cursor, current_variable){ + unsigned cursor2 = 0; + dw_variable_t current_variable; + xbt_dynar_foreach(stack_frame->frame->variables, cursor2, current_variable){ - if((uintptr_t)ip > (uintptr_t)start_text_libsimgrid) + int region_type; + if((long)stack_frame->ip > (long)mc_libsimgrid_info->start_exec) region_type = 1; else region_type = 2; local_variable_t new_var = xbt_new0(s_local_variable_t, 1); - new_var->frame = xbt_strdup(frame_name); - new_var->ip = (unsigned long)ip; + new_var->frame = xbt_strdup(stack_frame->frame_name); + new_var->ip = stack_frame->ip; new_var->name = xbt_strdup(current_variable->name); - new_var->type = strdup(current_variable->type_origin); + new_var->type = current_variable->type; new_var->region= region_type; - if(current_variable->address.location != NULL){ - switch(current_variable->address.location->type){ - case e_dw_compose: - if(xbt_dynar_length(current_variable->address.location->location.compose) > 1){ - /* TODO : location list with optimizations enabled */ - }else{ - location_entry = xbt_dynar_get_as(current_variable->address.location->location.compose, 0, dw_location_t); - - switch(location_entry->type){ - case e_dw_register: - unw_get_reg(&c, location_entry->location.reg, &res); - value = (unsigned long)res; - break; - case e_dw_bregister_op: - unw_get_reg(&c, location_entry->location.breg_op.reg, &res); - value = (unsigned long)res + location_entry->location.breg_op.offset; - break; - case e_dw_fbregister_op: - if(frame_pointer_address != NULL) - value = (unsigned long)((char *)frame_pointer_address + location_entry->location.fbreg_op); - else - value = 0; - break; - default: - value = 0; /* FIXME : implement other cases (with optimizations enabled)*/ - break; - } - - if(value) - new_var->address = (void *)value; - else - new_var->address = NULL; - } - break; - default : - break; - } + /* if(current_variable->address!=NULL) { + new_var->address = current_variable->address; + } else */ + if(current_variable->location != NULL){ + new_var->address = (void*) MC_dwarf_resolve_location( + &(stack_frame->unw_cursor), current_variable->location, (void*)stack_frame->frame_base); } xbt_dynar_push(variables, &new_var); } - - ret = unw_step(&c); - } return variables; } +static void MC_stack_frame_free_voipd(void *s){ + mc_stack_frame_t stack_frame = *(mc_stack_frame_t*)s; + if(stack_frame) { + xbt_free(stack_frame->frame_name); + xbt_free(stack_frame); + } +} -static void *MC_get_stack_pointer(void *stack_context, void *heap){ +static xbt_dynar_t MC_unwind_stack_frames(void *stack_context) { + xbt_dynar_t result = xbt_dynar_new(sizeof(mc_stack_frame_t), MC_stack_frame_free_voipd); unw_cursor_t c; + + dw_frame_t test = MC_find_function_by_ip(&MC_unwind_stack_frames); + xbt_assert(test); + int ret; - unw_word_t sp; + for(ret = unw_init_local(&c, (unw_context_t *)stack_context); ret >= 0; ret = unw_step(&c)){ + mc_stack_frame_t stack_frame = xbt_new(s_mc_stack_frame_t, 1); + xbt_dynar_push(result, &stack_frame); + + stack_frame->unw_cursor = c; + + unw_word_t ip, sp; + + unw_get_reg(&c, UNW_REG_IP, &ip); + unw_get_reg(&c, UNW_REG_SP, &sp); - ret = unw_init_local(&c, (unw_context_t *)stack_context); - if(ret < 0){ + stack_frame->ip = ip; + stack_frame->sp = sp; + + // TODO, use real addresses in frame_t instead of fixing it here + + dw_frame_t frame = MC_find_function_by_ip((void*) ip); + stack_frame->frame = frame; + + if(frame) { + stack_frame->frame_name = xbt_strdup(frame->name); + stack_frame->frame_base = (unw_word_t)mc_find_frame_base((void*)ip, frame, &c); + } else { + stack_frame->frame_base = 0; + } + + /* Stop before context switch with maestro */ + if(frame!=NULL && frame->name!=NULL && !strcmp(frame->name, "smx_ctx_sysv_wrapper")) + break; + } + + if(xbt_dynar_length(result) == 0){ XBT_INFO("unw_init_local failed"); xbt_abort(); } - unw_get_reg(&c, UNW_REG_SP, &sp); - - return (char *)heap + ((char *)sp - (char*)std_heap); - -} + return result; +}; static xbt_dynar_t MC_take_snapshot_stacks(mc_snapshot_t *snapshot, void *heap){ @@ -667,8 +343,12 @@ static xbt_dynar_t MC_take_snapshot_stacks(mc_snapshot_t *snapshot, void *heap){ xbt_dynar_foreach(stacks_areas, cursor, current_stack){ mc_snapshot_stack_t st = xbt_new(s_mc_snapshot_stack_t, 1); - st->local_variables = MC_get_local_variables_values(current_stack->context); - st->stack_pointer = MC_get_stack_pointer(current_stack->context, heap); + st->stack_frames = MC_unwind_stack_frames(current_stack->context); + st->local_variables = MC_get_local_variables_values(st->stack_frames); + + unw_word_t sp = xbt_dynar_get_as(st->stack_frames, 0, mc_stack_frame_t)->sp; + st->stack_pointer = ((char *)heap + (size_t)(((char *)((long)sp) - (char*)std_heap))); + st->real_address = current_stack->address; xbt_dynar_push(res, &st); (*snapshot)->stack_sizes = xbt_realloc((*snapshot)->stack_sizes, (cursor + 1) * sizeof(size_t)); @@ -737,8 +417,14 @@ mc_snapshot_t MC_take_snapshot(int num_state){ if(_sg_mc_visited > 0 || strcmp(_sg_mc_property_file,"")){ snapshot->stacks = MC_take_snapshot_stacks(&snapshot, snapshot->regions[0]->data); - //MC_get_hash_global(snapshot->hash_global, snapshot->regions[1]->data, snapshot->regions[2]->data); - //MC_get_hash_local(snapshot->hash_local, snapshot->stacks); + if(_sg_mc_hash && snapshot->stacks!=NULL) { + snapshot->hash = mc_hash_processes_state(num_state, snapshot->stacks); + } else { + snapshot->hash = 0; + } + } + else { + snapshot->hash = 0; } if(num_state > 0) diff --git a/src/mc/mc_compare.c b/src/mc/mc_compare.c index e017b7d376..5352c52c62 100644 --- a/src/mc/mc_compare.c +++ b/src/mc/mc_compare.c @@ -4,6 +4,8 @@ /* This program is free software; you can redistribute it and/or modify it * under the terms of the license (GNU LGPL) which comes with this package. */ +#include + #include "mc_private.h" #include "xbt/mmalloc.h" @@ -43,38 +45,12 @@ static void pointers_pair_free_voidp(void *p){ /************************** Snapshot comparison *******************************/ /******************************************************************************/ -static int already_compared_pointers(void *p1, void *p2){ - - if(xbt_dynar_is_empty(compared_pointers)) - return -1; - - unsigned int cursor = 0; - int start = 0; - int end = xbt_dynar_length(compared_pointers) - 1; - pointers_pair_t pair; - - while(start <= end){ - cursor = (start + end) / 2; - pair = (pointers_pair_t)xbt_dynar_get_as(compared_pointers, cursor, pointers_pair_t); - if(pair->p1 == p1){ - if(pair->p2 == p2) - return 0; - else if(pair->p2 < p2) - start = cursor + 1; - else - end = cursor - 1; - }else if(pair->p1 < p1){ - start = cursor + 1; - }else{ - end = cursor - 1 ; - } - } - - return -1; - -} - -static void add_compared_pointers(void *p1, void *p2){ +/** \brief Try to add a pair a compared pointers to the set of compared pointers + * + * \result !=0 if the pointers were added (they were not in the set), + * 0 otherwise (they were already in the set) + */ +static int add_compared_pointers(void *p1, void *p2){ pointers_pair_t new_pair = xbt_new0(s_pointers_pair_t, 1); new_pair->p1 = p1; @@ -82,7 +58,7 @@ static void add_compared_pointers(void *p1, void *p2){ if(xbt_dynar_is_empty(compared_pointers)){ xbt_dynar_push(compared_pointers, &new_pair); - return; + return 1; } unsigned int cursor = 0; @@ -90,103 +66,96 @@ static void add_compared_pointers(void *p1, void *p2){ int end = xbt_dynar_length(compared_pointers) - 1; pointers_pair_t pair = NULL; + pointers_pair_t* p = (pointers_pair_t*) xbt_dynar_get_ptr(compared_pointers, 0); + while(start <= end){ cursor = (start + end) / 2; - pair = (pointers_pair_t)xbt_dynar_get_as(compared_pointers, cursor, pointers_pair_t); - if(pair->p1 == p1){ - if(pair->p2 == p2){ - pointers_pair_free(new_pair); - return; - }else if(pair->p2 < p2) - start = cursor + 1; - else - end = cursor - 1; - }else if(pair->p1 < p1){ + pair = p[cursor]; + if(pair->p1 < p1){ start = cursor + 1; - }else{ + } else if(pair->p1 > p1) { + end = cursor - 1 ; + } else if(pair->p2 < p2){ + start = cursor + 1; + } else if(pair->p2 > p2) { end = cursor - 1 ; + } else { + pointers_pair_free(new_pair); + return 0; } } - if(pair->p1 == p1){ - if(pair->p2 < p2) - xbt_dynar_insert_at(compared_pointers, cursor + 1, &new_pair); - else - xbt_dynar_insert_at(compared_pointers, cursor, &new_pair); - }else{ - if(pair->p1 < p1) - xbt_dynar_insert_at(compared_pointers, cursor + 1, &new_pair); - else - xbt_dynar_insert_at(compared_pointers, cursor, &new_pair); - } - + if(pair->p1 < p1) + xbt_dynar_insert_at(compared_pointers, cursor + 1, &new_pair); + else if(pair->p1 > p1) + xbt_dynar_insert_at(compared_pointers, cursor, &new_pair); + else if(pair->p2 < p2) + xbt_dynar_insert_at(compared_pointers, cursor + 1, &new_pair); + else if(pair->p2 > p2) + xbt_dynar_insert_at(compared_pointers, cursor, &new_pair); + else + xbt_die("Unrecheable"); + + return 1; } -static int compare_areas_with_type(void *area1, void *area2, xbt_dict_t types, xbt_dict_t other_types, char *type_id, int region_size, int region_type, void *start_data, int pointer_level){ +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){ - dw_type_t type = xbt_dict_get_or_null(types, type_id);; 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 e_dw_base_type: - case e_dw_enumeration_type: - case e_dw_union_type: - return (memcmp(area1, area2, type->size) != 0); + 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 e_dw_typedef: - case e_dw_volatile_type: - return compare_areas_with_type(area1, area2, types, other_types, type->dw_type_id, region_size, region_type, start_data, pointer_level); + 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 e_dw_const_type: /* Const variable cannot be modified */ - return -1; - break; - case e_dw_array_type: - subtype = xbt_dict_get_or_null(types, type->dw_type_id); + case DW_TAG_array_type: + subtype = type->subtype; switch(subtype->type){ - case e_dw_base_type: - case e_dw_enumeration_type: - case e_dw_pointer_type: - case e_dw_structure_type: - case e_dw_union_type: - if(subtype->size == 0){ /*declaration of the type, need the complete description */ - subtype = xbt_dict_get_or_null(types, get_type_description(types, subtype->name)); - if(subtype == NULL){ - subtype = xbt_dict_get_or_null(other_types, get_type_description(other_types, subtype->name)); + 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 = subtype->other_object_same_type; switch_types = 1; - } } - elm_size = subtype->size; + elm_size = subtype->byte_size; break; - case e_dw_typedef: - case e_dw_volatile_type: - subsubtype = xbt_dict_get_or_null(types, subtype->dw_type_id); - if(subsubtype->size == 0){ /*declaration of the type, need the complete description */ - subsubtype = xbt_dict_get_or_null(types, get_type_description(types, subsubtype->name)); - if(subsubtype == NULL){ - subsubtype = xbt_dict_get_or_null(other_types, get_type_description(other_types, subsubtype->name)); + 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 = subsubtype->other_object_same_type; switch_types = 1; - } } - elm_size = subsubtype->size; + elm_size = subsubtype->byte_size; break; default : return 0; break; } - for(i=0; isize; i++){ + for(i=0; ielement_count; i++){ if(switch_types) - res = compare_areas_with_type((char *)area1 + (i*elm_size), (char *)area2 + (i*elm_size), other_types, types, type->dw_type_id, region_size, region_type, start_data, pointer_level); + 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), types, other_types, type->dw_type_id, region_size, region_type, start_data, pointer_level); + 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 e_dw_pointer_type: - if(type->dw_type_id && ((dw_type_t)xbt_dict_get_or_null(types, type->dw_type_id))->type == e_dw_subroutine_type){ + case DW_TAG_pointer_type: + if(type->subtype && type->subtype->type == DW_TAG_subroutine_type){ addr_pointed1 = *((void **)(area1)); addr_pointed2 = *((void **)(area2)); return (addr_pointed1 != addr_pointed2); @@ -196,32 +165,47 @@ static int compare_areas_with_type(void *area1, void *area2, xbt_dict_t types, x if(addr_pointed1 == NULL && addr_pointed2 == NULL) return 0; - if(already_compared_pointers(addr_pointed1, addr_pointed2) != -1) + if(!add_compared_pointers(addr_pointed1, addr_pointed2)) return 0; - add_compared_pointers(addr_pointed1, addr_pointed2); pointer_level++; - if(addr_pointed1 > std_heap && (char *)addr_pointed1 < (char*) std_heap + STD_HEAP_SIZE && addr_pointed2 > std_heap && (char *)addr_pointed2 < (char*) std_heap + STD_HEAP_SIZE){ - return compare_heap_area(addr_pointed1, addr_pointed2, NULL, types, other_types, type->dw_type_id, pointer_level); - }else if(addr_pointed1 > start_data && (char*)addr_pointed1 <= (char *)start_data + region_size && addr_pointed2 > start_data && (char*)addr_pointed2 <= (char *)start_data + region_size){ + // 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, types, other_types, type->dw_type_id, region_size, region_type, start_data, pointer_level); - }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); } } break; - case e_dw_structure_type: + case DW_TAG_structure_type: xbt_dynar_foreach(type->members, cursor, member){ - res = compare_areas_with_type((char *)area1 + member->offset, (char *)area2 + member->offset, types, other_types, member->dw_type_id, region_size, region_type, start_data, pointer_level); + XBT_DEBUG("Compare member %s", member->name); + res = compare_areas_with_type((char *)area1 + member->offset, (char *)area2 + member->offset, info, other_info, member->subtype, region_size, region_type, start_data, pointer_level); if(res == 1) return res; } break; - case e_dw_subroutine_type: + case DW_TAG_subroutine_type: return -1; break; default: @@ -242,33 +226,40 @@ static int compare_global_variables(int region_type, mc_mem_region_t r1, mc_mem_ } xbt_dynar_t variables; - xbt_dict_t types, other_types; int res; unsigned int cursor = 0; dw_variable_t current_var; size_t offset; void *start_data; + void* start_data_binary = mc_binary_info->start_rw; + void* start_data_libsimgrid = mc_libsimgrid_info->start_rw; + mc_object_info_t object_info = NULL; + mc_object_info_t other_object_info = NULL; if(region_type == 2){ - variables = mc_global_variables_binary; - types = mc_variables_type_binary; - other_types = mc_variables_type_libsimgrid; + object_info = mc_binary_info; + other_object_info = mc_libsimgrid_info; start_data = start_data_binary; }else{ - variables = mc_global_variables_libsimgrid; - types = mc_variables_type_libsimgrid; - other_types = mc_variables_type_binary; + object_info = mc_libsimgrid_info; + other_object_info = mc_binary_info; start_data = start_data_libsimgrid; } + variables = object_info->global_variables; xbt_dynar_foreach(variables, cursor, current_var){ - if(region_type == 2) - offset = (char *)current_var->address.address - (char *)start_data_binary; - else - offset = (char *)current_var->address.address - (char *)start_data_libsimgrid; + // If the variable is not in this object, skip it: + // We do not expect to find a pointer to something which is not reachable + // by the global variables. + if((char*) current_var->address < (char*) object_info->start_rw + || (char*) current_var->address > (char*) object_info->end_rw) + continue; + + offset = (char *)current_var->address - (char *)object_info->start_rw; - res = compare_areas_with_type((char *)r1->data + offset, (char *)r2->data + offset, types, other_types, current_var->type_origin, r1->size, region_type, start_data, 0); + dw_type_t bvariable_type = current_var->type; + res = compare_areas_with_type((char *)r1->data + offset, (char *)r2->data + offset, object_info, other_object_info, bvariable_type, r1->size, region_type, start_data, 0); if(res == 1){ XBT_VERB("Global variable %s (%p - %p) is different between snapshots", current_var->name, (char *)r1->data + offset, (char *)r2->data + offset); xbt_dynar_free(&compared_pointers); @@ -286,6 +277,8 @@ static int compare_global_variables(int region_type, mc_mem_region_t r1, mc_mem_ } static int compare_local_variables(mc_snapshot_stack_t stack1, mc_snapshot_stack_t stack2, void *heap1, void *heap2){ + void* start_data_binary = mc_binary_info->start_rw; + void* start_data_libsimgrid = mc_libsimgrid_info->start_rw; if(!compared_pointers){ compared_pointers = xbt_dynar_new(sizeof(pointers_pair_t), pointers_pair_free_voidp); @@ -313,10 +306,16 @@ static int compare_local_variables(mc_snapshot_stack_t stack1, mc_snapshot_stack } offset1 = (char *)current_var1->address - (char *)std_heap; offset2 = (char *)current_var2->address - (char *)std_heap; - if(current_var1->region == 1) - res = compare_areas_with_type( (char *)heap1 + offset1, (char *)heap2 + offset2, mc_variables_type_libsimgrid, mc_variables_type_binary, current_var1->type, 0, 1, start_data_libsimgrid, 0); - else - res = compare_areas_with_type( (char *)heap1 + offset1, (char *)heap2 + offset2, mc_variables_type_binary, mc_variables_type_libsimgrid, current_var1->type, 0, 2, start_data_binary, 0); + XBT_DEBUG("Compare local variable %s of frame %s", current_var1->name, current_var1->frame); + + + if(current_var1->region == 1) { + dw_type_t subtype = current_var1->type; + res = compare_areas_with_type( (char *)heap1 + offset1, (char *)heap2 + offset2, mc_libsimgrid_info, mc_binary_info, subtype, 0, 1, start_data_libsimgrid, 0); + } else { + dw_type_t subtype = current_var2->type; + res = compare_areas_with_type( (char *)heap1 + offset1, (char *)heap2 + offset2, mc_binary_info, mc_libsimgrid_info, subtype, 0, 2, start_data_binary, 0); + } if(res == 1){ XBT_VERB("Local variable %s (%p - %p) in frame %s is different between snapshots", current_var1->name,(char *)heap1 + offset1, (char *)heap2 + offset2, current_var1->frame); xbt_dynar_free(&compared_pointers); @@ -365,10 +364,25 @@ int snapshot_compare(void *state1, void *state2){ xbt_os_walltimer_start(timer); #endif - /* Compare size of stacks */ + int hash_result = 0; + if(_sg_mc_hash) { + hash_result = (s1->hash != s2->hash); + if(hash_result) { + XBT_VERB("(%d - %d) Different hash : 0x%" PRIx64 "--0x%" PRIx64, num1, num2, s1->hash, s2->hash); +#ifndef MC_DEBUG + return 1; +#endif + } else { + XBT_VERB("(%d - %d) Same hash : 0x%" PRIx64, num1, num2, s1->hash); + } + } + int i = 0; size_t size_used1, size_used2; int is_diff = 0; + + + /* Compare size of stacks */ while(i < xbt_dynar_length(s1->stacks)){ size_used1 = s1->stack_sizes[i]; size_used2 = s2->stack_sizes[i]; @@ -404,62 +418,6 @@ int snapshot_compare(void *state1, void *state2){ xbt_os_walltimer_start(timer); #endif - /* Compare hash of global variables */ - if(s1->hash_global != NULL && s2->hash_global != NULL){ - if(strcmp(s1->hash_global, s2->hash_global) != 0){ - #ifdef MC_DEBUG - xbt_os_walltimer_stop(timer); - mc_comp_times->hash_global_variables_comparison_time = xbt_os_timer_elapsed(timer); - XBT_DEBUG("Different hash of global variables : %s - %s", s1->hash_global, s2->hash_global); - errors++; - #else - #ifdef MC_VERBOSE - XBT_VERB("Different hash of global variables : %s - %s", s1->hash_global, s2->hash_global); - #endif - - xbt_os_walltimer_stop(timer); - xbt_os_timer_free(timer); - xbt_os_walltimer_stop(global_timer); - mc_snapshot_comparison_time = xbt_os_timer_elapsed(global_timer); - xbt_os_timer_free(global_timer); - - return 1; - #endif - } - } - - #ifdef MC_DEBUG - xbt_os_walltimer_start(timer); - #endif - - /* Compare hash of local variables */ - if(s1->hash_local != NULL && s2->hash_local != NULL){ - if(strcmp(s1->hash_local, s2->hash_local) != 0){ - #ifdef MC_DEBUG - xbt_os_walltimer_stop(timer); - mc_comp_times->hash_local_variables_comparison_time = xbt_os_timer_elapsed(timer); - XBT_DEBUG("Different hash of local variables : %s - %s", s1->hash_local, s2->hash_local); - errors++; - #else - #ifdef MC_VERBOSE - XBT_VERB("Different hash of local variables : %s - %s", s1->hash_local, s2->hash_local); - #endif - - xbt_os_walltimer_stop(timer); - xbt_os_timer_free(timer); - xbt_os_walltimer_stop(global_timer); - mc_snapshot_comparison_time = xbt_os_timer_elapsed(global_timer); - xbt_os_timer_free(global_timer); - - return 1; - #endif - } - } - - #ifdef MC_DEBUG - xbt_os_walltimer_start(timer); - #endif - /* Init heap information used in heap comparison algorithm */ res_init = init_heap_information((xbt_mheap_t)s1->regions[0]->data, (xbt_mheap_t)s2->regions[0]->data, s1->to_ignore, s2->to_ignore); if(res_init == -1){ @@ -521,55 +479,38 @@ int snapshot_compare(void *state1, void *state2){ cursor++; } - #ifdef MC_DEBUG - if(is_diff == 0) - xbt_os_walltimer_stop(timer); - xbt_os_walltimer_start(timer); - #endif - /* Compare binary global variables */ - is_diff = compare_global_variables(2, s1->regions[2], s2->regions[2]); - if(is_diff != 0){ - #ifdef MC_DEBUG - xbt_os_walltimer_stop(timer); - mc_comp_times->binary_global_variables_comparison_time = xbt_os_timer_elapsed(timer); - XBT_DEBUG("(%d - %d) Different global variables in binary", num1, num2); - errors++; - #else - #ifdef MC_VERBOSE - XBT_VERB("(%d - %d) Different global variables in binary", num1, num2); - #endif - reset_heap_information(); - xbt_os_walltimer_stop(timer); - xbt_os_timer_free(timer); - xbt_os_walltimer_stop(global_timer); - mc_snapshot_comparison_time = xbt_os_timer_elapsed(global_timer); - xbt_os_timer_free(global_timer); + const char* names[3] = { "?", "libsimgrid", "binary" }; +#ifdef MC_DEBUG + double *times[3] = { + NULL, + &mc_comp_times->libsimgrid_global_variables_comparison_time, + &mc_comp_times->binary_global_variables_comparison_time + }; +#endif - return 1; + int k=0; + for(k=2; k!=0; --k) { + #ifdef MC_DEBUG + if(is_diff == 0) + xbt_os_walltimer_stop(timer); + xbt_os_walltimer_start(timer); #endif - } - #ifdef MC_DEBUG - if(is_diff == 0) - xbt_os_walltimer_stop(timer); - xbt_os_walltimer_start(timer); - #endif - - /* Compare libsimgrid global variables */ - is_diff = compare_global_variables(1, s1->regions[1], s2->regions[1]); + /* Compare global variables */ + is_diff = compare_global_variables(k, s1->regions[k], s2->regions[k]); if(is_diff != 0){ #ifdef MC_DEBUG xbt_os_walltimer_stop(timer); - mc_comp_times->libsimgrid_global_variables_comparison_time = xbt_os_timer_elapsed(timer); - XBT_DEBUG("(%d - %d) Different global variables in libsimgrid", num1, num2); + *times[k] = xbt_os_timer_elapsed(timer); + XBT_DEBUG("(%d - %d) Different global variables in %s", num1, num2, names[k]); errors++; #else #ifdef MC_VERBOSE - XBT_VERB("(%d - %d) Different global variables in libsimgrid", num1, num2); + XBT_VERB("(%d - %d) Different global variables in %s", num1, num2, names[k]); #endif - + reset_heap_information(); xbt_os_walltimer_stop(timer); xbt_os_timer_free(timer); @@ -580,13 +521,17 @@ int snapshot_compare(void *state1, void *state2){ return 1; #endif } + } #ifdef MC_DEBUG xbt_os_walltimer_start(timer); #endif /* Compare heap */ - if(mmalloc_compare_heap((xbt_mheap_t)s1->regions[0]->data, (xbt_mheap_t)s2->regions[0]->data, mc_variables_type_libsimgrid, mc_variables_type_binary) > 0){ + if(mmalloc_compare_heap((xbt_mheap_t)s1->regions[0]->data, + (xbt_mheap_t)s2->regions[0]->data, + mc_libsimgrid_info, + mc_binary_info) > 0){ #ifdef MC_DEBUG xbt_os_walltimer_stop(timer); @@ -630,7 +575,25 @@ int snapshot_compare(void *state1, void *state2){ print_comparison_times(); #endif - return errors > 0; +#ifdef MC_VERBOSE + if(errors || hash_result) + XBT_VERB("(%d - %d) Difference found", num1, num2); + else + XBT_VERB("(%d - %d) No difference found", num1, num2); +#endif + +#if defined(MC_DEBUG) && defined(MC_VERBOSE) + if(_sg_mc_hash) { + // * false positive SHOULD be avoided. + // * There MUST not be any false negative. + + XBT_VERB("(%d - %d) State equality hash test is %s %s", num1, num2, + (hash_result!=0) == (errors!=0) ? "true" : "false", + !hash_result ? "positive" : "negative"); + } +#endif + + return errors > 0 || hash_result; } diff --git a/src/mc/mc_dpor.c b/src/mc/mc_dpor.c index fb3c12063a..1d102d3d90 100644 --- a/src/mc/mc_dpor.c +++ b/src/mc/mc_dpor.c @@ -13,9 +13,154 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_dpor, mc, xbt_dynar_t visited_states; xbt_dict_t first_enabled_state; +xbt_dynar_t initial_communications_pattern; +xbt_dynar_t communications_pattern; +int nb_comm_pattern; /********** Static functions ***********/ +static void comm_pattern_free(mc_comm_pattern_t p){ + xbt_free(p->rdv); + xbt_free(p->data); + xbt_free(p); + p = NULL; +} + +static void comm_pattern_free_voidp( void *p){ + comm_pattern_free((mc_comm_pattern_t) * (void **)p); +} + +static mc_comm_pattern_t get_comm_pattern_from_idx(xbt_dynar_t pattern, unsigned int *idx, e_smx_comm_type_t type, unsigned long proc){ + mc_comm_pattern_t current_comm; + while(*idx < xbt_dynar_length(pattern)){ + current_comm = (mc_comm_pattern_t)xbt_dynar_get_as(pattern, *idx, mc_comm_pattern_t); + if(current_comm->type == type && type == SIMIX_COMM_SEND){ + if(current_comm->src_proc == proc) + return current_comm; + }else if(current_comm->type == type && type == SIMIX_COMM_RECEIVE){ + if(current_comm->dst_proc == proc) + return current_comm; + } + (*idx)++; + } + return NULL; +} + +static int compare_comm_pattern(mc_comm_pattern_t comm1, mc_comm_pattern_t comm2){ + if(strcmp(comm1->rdv, comm2->rdv) != 0) + return 1; + if(comm1->src_proc != comm2->src_proc) + return 1; + if(comm1->dst_proc != comm2->dst_proc) + return 1; + if(comm1->data_size != comm2->data_size) + return 1; + if(memcmp(comm1->data, comm2->data, comm1->data_size) != 0) + return 1; + return 0; +} + +static void deterministic_pattern(xbt_dynar_t initial_pattern, xbt_dynar_t pattern){ + unsigned int cursor = 0, send_index = 0, recv_index = 0; + mc_comm_pattern_t comm1, comm2; + int comm_comparison = 0; + int current_process = 0; + while(current_process < simix_process_maxpid){ + while(cursor < xbt_dynar_length(initial_pattern)){ + comm1 = (mc_comm_pattern_t)xbt_dynar_get_as(initial_pattern, cursor, mc_comm_pattern_t); + if(comm1->type == SIMIX_COMM_SEND && comm1->src_proc == current_process){ + comm2 = get_comm_pattern_from_idx(pattern, &send_index, comm1->type, current_process); + comm_comparison = compare_comm_pattern(comm1, comm2); + if(comm_comparison == 1){ + initial_state_safety->send_deterministic = 0; + initial_state_safety->comm_deterministic = 0; + return; + } + send_index++; + }else if(comm1->type == SIMIX_COMM_RECEIVE && comm1->dst_proc == current_process){ + comm2 = get_comm_pattern_from_idx(pattern, &recv_index, comm1->type, current_process); + comm_comparison = compare_comm_pattern(comm1, comm2); + if(comm_comparison == 1){ + initial_state_safety->comm_deterministic = 0; + } + recv_index++; + } + cursor++; + } + cursor = 0; + send_index = 0; + recv_index = 0; + current_process++; + } + // XBT_DEBUG("Communication-deterministic : %d, Send-deterministic : %d", initial_state_safety->comm_deterministic, initial_state_safety->send_deterministic); +} + +static int complete_comm_pattern(xbt_dynar_t list, mc_comm_pattern_t pattern){ + mc_comm_pattern_t current_pattern; + unsigned int cursor = 0; + xbt_dynar_foreach(list, cursor, current_pattern){ + if(current_pattern->comm == pattern->comm){ + if(!current_pattern->completed){ + current_pattern->src_proc = pattern->comm->comm.src_proc->pid; + current_pattern->dst_proc = pattern->comm->comm.dst_proc->pid; + current_pattern->data_size = pattern->comm->comm.src_buff_size; + current_pattern->data = xbt_malloc0(current_pattern->data_size); + current_pattern->matched_comm = pattern->num; + memcpy(current_pattern->data, current_pattern->comm->comm.src_buff, current_pattern->data_size); + current_pattern->completed = 1; + return current_pattern->num; + } + } + } + return -1; +} + +void get_comm_pattern(xbt_dynar_t list, smx_simcall_t request, int call){ + mc_comm_pattern_t pattern = NULL; + pattern = xbt_new0(s_mc_comm_pattern_t, 1); + pattern->num = ++nb_comm_pattern; + pattern->completed = 0; + if(call == 1){ // ISEND + pattern->comm = simcall_comm_isend__get__result(request); + pattern->type = SIMIX_COMM_SEND; + if(pattern->comm->comm.dst_proc != NULL){ + + pattern->matched_comm = complete_comm_pattern(list, pattern); + pattern->dst_proc = pattern->comm->comm.dst_proc->pid; + pattern->completed = 1; + } + pattern->src_proc = pattern->comm->comm.src_proc->pid; + pattern->data_size = pattern->comm->comm.src_buff_size; + pattern->data=xbt_malloc0(pattern->data_size); + memcpy(pattern->data, pattern->comm->comm.src_buff, pattern->data_size); + }else{ // IRECV + pattern->comm = simcall_comm_irecv__get__result(request); + pattern->type = SIMIX_COMM_RECEIVE; + if(pattern->comm->comm.src_proc != NULL){ + pattern->matched_comm = complete_comm_pattern(list, pattern); + pattern->src_proc = pattern->comm->comm.src_proc->pid; + pattern->completed = 1; + pattern->data_size = pattern->comm->comm.src_buff_size; + pattern->data=xbt_malloc0(pattern->data_size); + memcpy(pattern->data, pattern->comm->comm.src_buff, pattern->data_size); + } + pattern->dst_proc = pattern->comm->comm.dst_proc->pid; + } + if(pattern->comm->comm.rdv != NULL) + pattern->rdv = strdup(pattern->comm->comm.rdv->name); + else + pattern->rdv = strdup(pattern->comm->comm.rdv_cpy->name); + xbt_dynar_push(list, &pattern); +} + +static void print_communications_pattern(xbt_dynar_t comms_pattern){ + unsigned int cursor = 0; + mc_comm_pattern_t current_comm; + xbt_dynar_foreach(comms_pattern, cursor, current_comm){ + // fprintf(stderr, "%s (%d - comm %p, src : %lu, dst %lu, rdv name %s, data %p, matched with %d)\n", current_comm->type == SIMIX_COMM_SEND ? "iSend" : "iRecv", current_comm->num, current_comm->comm, current_comm->src_proc, current_comm->dst_proc, current_comm->rdv, current_comm->data, current_comm->matched_comm); + } +} + static void visited_state_free(mc_visited_state_t state){ if(state){ MC_free_snapshot(state->system_state); @@ -27,6 +172,10 @@ static void visited_state_free_voidp(void *s){ visited_state_free((mc_visited_state_t) * (void **) s); } +/** \brief Save the current state + * + * \return Snapshot of the current state. + */ static mc_visited_state_t visited_state_new(){ mc_visited_state_t new_state = NULL; @@ -41,6 +190,22 @@ static mc_visited_state_t visited_state_new(){ } +/** \brief Find a suitable subrange of candidate duplicates for a given state + * + * \param all_ pairs dynamic array of states with candidate duplicates of the current state; + * \param pair current state; + * \param min (output) index of the beginning of the the subrange + * \param max (output) index of the enf of the subrange + * + * Given a suitably ordered array of state, this function extracts a subrange + * (with index *min <= i <= *max) with candidate duplicates of the given state. + * This function uses only fast discriminating criterions and does not use the + * full state comparison algorithms. + * + * The states in all_pairs MUST be ordered using a (given) weak order + * (based on nb_processes and heap_bytes_used). + * The subrange is the subrange of "equivalence" of the given state. + */ static int get_search_interval(xbt_dynar_t all_states, mc_visited_state_t state, int *min, int *max){ int raw_mem_set = (mmalloc_get_current_heap() == raw_heap); @@ -95,6 +260,10 @@ static int get_search_interval(xbt_dynar_t all_states, mc_visited_state_t state, return cursor; } +/** \brief Take a snapshot the current state and process it. + * + * \return number of the duplicate state or -1 (not visited) + */ static int is_visited_state(){ if(_sg_mc_visited == 0) @@ -125,6 +294,8 @@ static int is_visited_state(){ index = get_search_interval(visited_states, new_state, &min, &max); if(min != -1 && max != -1){ + + // Parallell implementation /*res = xbt_parmap_mc_apply(parmap, snapshot_compare, xbt_dynar_get_ptr(visited_states, min), (max-min)+1, new_state); if(res != -1){ state_test = (mc_visited_state_t)xbt_dynar_get_as(visited_states, (min+res)-1, mc_visited_state_t); @@ -142,10 +313,13 @@ static int is_visited_state(){ MC_UNSET_RAW_MEM; return new_state->other_num; }*/ + cursor = min; while(cursor <= max){ state_test = (mc_visited_state_t)xbt_dynar_get_as(visited_states, cursor, mc_visited_state_t); if(snapshot_compare(state_test, new_state) == 0){ + // The state has been visited: + if(state_test->other_num == -1) new_state->other_num = state_test->num; else @@ -154,16 +328,24 @@ static int is_visited_state(){ XBT_DEBUG("State %d already visited ! (equal to state %d)", new_state->num, state_test->num); else XBT_DEBUG("State %d already visited ! (equal to state %d (state %d in dot_output))", new_state->num, state_test->num, new_state->other_num); + + // Replace the old state with the new one (why?): xbt_dynar_remove_at(visited_states, cursor, NULL); xbt_dynar_insert_at(visited_states, cursor, &new_state); + if(!raw_mem_set) MC_UNSET_RAW_MEM; return new_state->other_num; } cursor++; } + + // The state has not been visited, add it to the list: xbt_dynar_insert_at(visited_states, min, &new_state); + }else{ + + // The state has not been visited: insert the state in the dynamic array. state_test = (mc_visited_state_t)xbt_dynar_get_as(visited_states, index, mc_visited_state_t); if(state_test->nb_processes < new_state->nb_processes){ xbt_dynar_insert_at(visited_states, index+1, &new_state); @@ -173,9 +355,13 @@ static int is_visited_state(){ else xbt_dynar_insert_at(visited_states, index, &new_state); } + } + // We have reached the maximum number of stored states; if(xbt_dynar_length(visited_states) > _sg_mc_visited){ + + // Find the (index of the) older state: int min2 = mc_stats->expanded_states; unsigned int cursor2 = 0; unsigned int index2 = 0; @@ -185,6 +371,8 @@ static int is_visited_state(){ min2 = state_test->num; } } + + // and drop it: xbt_dynar_remove_at(visited_states, index2, NULL); } @@ -210,12 +398,17 @@ void MC_dpor_init() /* Create the initial state and push it into the exploration stack */ MC_SET_RAW_MEM; - initial_state = MC_state_new(); if(_sg_mc_visited > 0) visited_states = xbt_dynar_new(sizeof(mc_visited_state_t), visited_state_free_voidp); first_enabled_state = xbt_dict_new_homogeneous(&xbt_free_f); + initial_communications_pattern = xbt_dynar_new(sizeof(mc_comm_pattern_t), comm_pattern_free_voidp); + communications_pattern = xbt_dynar_new(sizeof(mc_comm_pattern_t), comm_pattern_free_voidp); + nb_comm_pattern = 0; + + initial_state = MC_state_new(); + MC_UNSET_RAW_MEM; XBT_DEBUG("**************************************************"); @@ -263,9 +456,8 @@ void MC_dpor_init() } -/** - * \brief Perform the model-checking operation using a depth-first search exploration - * with Dynamic Partial Order Reductions +/** \brief Model-check the application using a DFS exploration + * with DPOR (Dynamic Partial Order Reductions) */ void MC_dpor(void) { @@ -273,13 +465,15 @@ void MC_dpor(void) char *req_str = NULL; int value; smx_simcall_t req = NULL, prev_req = NULL; - mc_state_t state = NULL, prev_state = NULL, next_state = NULL, restore_state=NULL; + mc_state_t state = NULL, prev_state = NULL, next_state = NULL, restored_state=NULL; smx_process_t process = NULL; xbt_fifo_item_t item = NULL; mc_state_t state_test = NULL; int pos; int visited_state = -1; int enabled = 0; + int interleave_size = 0; + int comm_pattern = 0; while (xbt_fifo_size(mc_stack_safety) > 0) { @@ -292,6 +486,8 @@ void MC_dpor(void) xbt_fifo_size(mc_stack_safety), state, state->num, MC_state_interleave_size(state), user_max_depth_reached, xbt_dict_size(first_enabled_state)); + interleave_size = MC_state_interleave_size(state); + /* Update statistics */ mc_stats->visited_states++; @@ -320,10 +516,29 @@ void MC_dpor(void) xbt_dict_remove(first_enabled_state, key); xbt_free(key); MC_UNSET_RAW_MEM; + + if(_sg_mc_comms_determinism){ + if(req->call == SIMCALL_COMM_ISEND) + comm_pattern = 1; + else if(req->call == SIMCALL_COMM_IRECV) + comm_pattern = 2; + } /* Answer the request */ SIMIX_simcall_pre(req, value); /* After this call req is no longer usefull */ + if(_sg_mc_comms_determinism){ + MC_SET_RAW_MEM; + if(comm_pattern != 0){ + if(!initial_state_safety->initial_communications_pattern_done) + get_comm_pattern(initial_communications_pattern, req, comm_pattern); + else + get_comm_pattern(communications_pattern, req, comm_pattern); + } + MC_UNSET_RAW_MEM; + comm_pattern = 0; + } + /* Wait for requests (schedules processes) */ MC_wait_for_requests(); @@ -415,11 +630,25 @@ void MC_dpor(void) } - /* Trash the current state, no longer needed */ MC_SET_RAW_MEM; + + if(_sg_mc_comms_determinism){ + if(!initial_state_safety->initial_communications_pattern_done){ + //print_communications_pattern(initial_communications_pattern); + }else{ + if(interleave_size == 0){ /* if (interleave_size > 0), process interleaved but not enabled => "incorrect" path, determinism not evaluated */ + //print_communications_pattern(communications_pattern); + deterministic_pattern(initial_communications_pattern, communications_pattern); + } + } + initial_state_safety->initial_communications_pattern_done = 1; + } + + /* Trash the current state, no longer needed */ xbt_fifo_shift(mc_stack_safety); MC_state_delete(state); XBT_DEBUG("Delete state %d at depth %d", state->num, xbt_fifo_size(mc_stack_safety) + 1); + MC_UNSET_RAW_MEM; /* Check for deadlocks */ @@ -485,15 +714,15 @@ void MC_dpor(void) pos = xbt_fifo_size(mc_stack_safety); item = xbt_fifo_get_first_item(mc_stack_safety); while(pos>0){ - restore_state = (mc_state_t) xbt_fifo_get_item_content(item); - if(restore_state->system_state != NULL){ + restored_state = (mc_state_t) xbt_fifo_get_item_content(item); + if(restored_state->system_state != NULL){ break; }else{ item = xbt_fifo_get_next_item(item); pos--; } } - MC_restore_snapshot(restore_state->system_state); + MC_restore_snapshot(restored_state->system_state); xbt_fifo_unshift(mc_stack_safety, state); MC_UNSET_RAW_MEM; MC_replay(mc_stack_safety, pos); @@ -506,6 +735,13 @@ void MC_dpor(void) XBT_DEBUG("Back-tracking to state %d at depth %d done", state->num, xbt_fifo_size(mc_stack_safety)); break; } else { + req = MC_state_get_internal_request(state); + if(_sg_mc_comms_determinism){ + if(req->call == SIMCALL_COMM_ISEND || req->call == SIMCALL_COMM_IRECV){ + if(!xbt_dynar_is_empty(communications_pattern)) + xbt_dynar_remove_at(communications_pattern, xbt_dynar_length(communications_pattern) - 1, NULL); + } + } XBT_DEBUG("Delete state %d at depth %d", state->num, xbt_fifo_size(mc_stack_safety) + 1); MC_state_delete(state); } diff --git a/src/mc/mc_dwarf.c b/src/mc/mc_dwarf.c new file mode 100644 index 0000000000..3107c9d7ba --- /dev/null +++ b/src/mc/mc_dwarf.c @@ -0,0 +1,1010 @@ +/* Copyright (c) 2008-2013. The SimGrid Team. + * All rights reserved. */ +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "mc_private.h" + +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_dwarf, mc, "DWARF processing"); + +/** \brief The default DW_TAG_lower_bound for a given DW_AT_language. + * + * The default for a given language is defined in the DWARF spec. + * + * \param language consant as defined by the DWARf spec + */ +static uint64_t MC_dwarf_default_lower_bound(int lang); + +/** \brief Computes the the element_count of a DW_TAG_enumeration_type DIE + * + * This is the number of elements in a given array dimension. + * + * A reference of the compilation unit (DW_TAG_compile_unit) is + * needed because the default lower bound (when there is no DW_AT_lower_bound) + * depends of the language of the compilation unit (DW_AT_language). + * + * \param die DIE for the DW_TAG_enumeration_type or DW_TAG_subrange_type + * \param unit DIE of the DW_TAG_compile_unit + */ +static uint64_t MC_dwarf_subrange_element_count(Dwarf_Die* die, Dwarf_Die* unit); + +/** \brief Computes the number of elements of a given DW_TAG_array_type. + * + * \param die DIE for the DW_TAG_array_type + */ +static uint64_t MC_dwarf_array_element_count(Dwarf_Die* die, Dwarf_Die* unit); + +/** \brief Process a DIE + * + * \param info the resulting object fot the library/binary file (output) + * \param die the current DIE + * \param unit the DIE of the compile unit of the current DIE + * \param frame containg frame if any + */ +static void MC_dwarf_handle_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame); + +/** \brief Process a type DIE + */ +static void MC_dwarf_handle_type_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit); + +/** \brief Calls MC_dwarf_handle_die on all childrend of the given die + * + * \param info the resulting object fot the library/binary file (output) + * \param die the current DIE + * \param unit the DIE of the compile unit of the current DIE + * \param frame containg frame if any + */ +static void MC_dwarf_handle_children(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame); + +/** \brief Handle a variable (DW_TAG_variable or other) + * + * \param info the resulting object fot the library/binary file (output) + * \param die the current DIE + * \param unit the DIE of the compile unit of the current DIE + * \param frame containg frame if any + */ +static void MC_dwarf_handle_variable_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame); + +/** \brief Convert a libdw DWARF expression into a MC representation of the location + * + * \param expr array of DWARf operations + * \param len number of elements + * \return a new MC expression + */ +static dw_location_t MC_dwarf_get_expression(Dwarf_Op* expr, size_t len); + +/** \brief Get the DW_TAG_type of the DIE + * + * \param die DIE + * \return DW_TAG_type attribute as a new string (NULL if none) + */ +static char* MC_dwarf_at_type(Dwarf_Die* die); + +/** \brief Get the name of an attribute (DW_AT_*) from its code + * + * \param attr attribute code (see the DWARF specification) + * \return name of the attribute + */ +const char* MC_dwarf_attrname(int attr) { + switch (attr) { +#include "mc_dwarf_attrnames.h" + default: + return "DW_AT_unkown"; + } +} + +/** \brief Get the name of a dwarf tag (DW_TAG_*) from its code + * + * \param tag tag code (see the DWARF specification) + * \return name of the tag + */ +const char* MC_dwarf_tagname(int tag) { + switch (tag) { +#include "mc_dwarf_tagnames.h" + case DW_TAG_invalid: + return "DW_TAG_invalid"; + default: + return "DW_TAG_unkown"; + } +} + +#define MC_DW_CLASS_UNKNOWN 0 +#define MC_DW_CLASS_ADDRESS 1 // Location in the address space of the program +#define MC_DW_CLASS_BLOCK 2 // Arbitrary block of bytes +#define MC_DW_CLASS_CONSTANT 3 +#define MC_DW_CLASS_STRING 3 // String +#define MC_DW_CLASS_FLAG 4 // Boolean +#define MC_DW_CLASS_REFERENCE 5 // Reference to another DIE +#define MC_DW_CLASS_EXPRLOC 6 // DWARF expression/location description +#define MC_DW_CLASS_LINEPTR 7 +#define MC_DW_CLASS_LOCLISTPTR 8 +#define MC_DW_CLASS_MACPTR 9 +#define MC_DW_CLASS_RANGELISTPTR 10 + +static int MC_dwarf_form_get_class(int form) { + switch(form) { + case DW_FORM_addr: + return MC_DW_CLASS_ADDRESS; + case DW_FORM_block2: + case DW_FORM_block4: + case DW_FORM_block: + case DW_FORM_block1: + return MC_DW_CLASS_BLOCK; + case DW_FORM_data2: + case DW_FORM_data4: + case DW_FORM_data8: + case DW_FORM_udata: + case DW_FORM_sdata: + return MC_DW_CLASS_CONSTANT; + case DW_FORM_string: + case DW_FORM_strp: + return MC_DW_CLASS_STRING; + case DW_FORM_ref_addr: + case DW_FORM_ref1: + case DW_FORM_ref2: + case DW_FORM_ref4: + case DW_FORM_ref8: + case DW_FORM_ref_udata: + return MC_DW_CLASS_REFERENCE; + case DW_FORM_flag: + case DW_FORM_flag_present: + return MC_DW_CLASS_FLAG; + case DW_FORM_exprloc: + return MC_DW_CLASS_EXPRLOC; + // TODO sec offset + // TODO indirect + default: + return MC_DW_CLASS_UNKNOWN; + } +} + +/** \brief Get the name of the tag of a given DIE + * + * \param die DIE + * \return name of the tag of this DIE + */ +static inline const char* MC_dwarf_die_tagname(Dwarf_Die* die) { + return MC_dwarf_tagname(dwarf_tag(die)); +} + +// ***** Attributes + +/** \brief Get an attribute of a given DIE as a string + * + * \param the DIE + * \param attribute attribute + * \return value of the given attribute of the given DIE + */ +static const char* MC_dwarf_attr_string(Dwarf_Die* die, int attribute) { + Dwarf_Attribute attr; + if (!dwarf_attr_integrate(die, attribute, &attr)) { + return NULL; + } else { + return dwarf_formstring(&attr); + } +} + +/** \brief Get the linkage name of a DIE. + * + * Use either DW_AT_linkage_name or DW_AR_MIPS_linkage_name. + * + * \param DIE + * \return linkage name of the given DIE (or NULL) + * */ +static const char* MC_dwarf_at_linkage_name(Dwarf_Die* die) { + const char* name = MC_dwarf_attr_string(die, DW_AT_linkage_name); + if (!name) + name = MC_dwarf_attr_string(die, DW_AT_MIPS_linkage_name); + return name; +} + +/** \brief Create a location list from a given attribute + * + * \param die the DIE + * \param attr the attribute + * \return MC specific representation of the location list represented by the given attribute + * of the given die + */ +static dw_location_t MC_dwarf_get_location_list(mc_object_info_t info, Dwarf_Die* die, Dwarf_Attribute* attr) { + + dw_location_t location = xbt_new0(s_dw_location_t, 1); + location->type = e_dw_loclist; + xbt_dynar_t loclist = xbt_dynar_new(sizeof(dw_location_entry_t), NULL); + location->location.loclist = loclist; + + ptrdiff_t offset = 0; + Dwarf_Addr base, start, end; + Dwarf_Op *expr; + size_t len; + + while (1) { + + offset = dwarf_getlocations(attr, offset, &base, &start, &end, &expr, &len); + if (offset==0) + return location; + else if (offset==-1) + xbt_die("Error while loading location list"); + + dw_location_entry_t new_entry = xbt_new0(s_dw_location_entry_t, 1); + + void* base = info->flags & MC_OBJECT_INFO_EXECUTABLE ? 0 : MC_object_base_address(info); + + new_entry->lowpc = (char*) base + start; + new_entry->highpc = (char*) base + end; + new_entry->location = MC_dwarf_get_expression(expr, len); + + xbt_dynar_push(loclist, &new_entry); + + } +} + +/** \brief Find the frame base of a given frame + * + * \param ip Instruction pointer + * \param frame + * \param unw_cursor + */ +void* mc_find_frame_base(void* ip, dw_frame_t frame, unw_cursor_t* unw_cursor) { + switch(frame->frame_base->type) { + case e_dw_loclist: + { + int loclist_cursor; + for(loclist_cursor=0; loclist_cursor < xbt_dynar_length(frame->frame_base->location.loclist); loclist_cursor++){ + dw_location_entry_t entry = xbt_dynar_get_as(frame->frame_base->location.loclist, loclist_cursor, dw_location_entry_t); + if((ip >= entry->lowpc) && (ip < entry->highpc)){ + return (void*) MC_dwarf_resolve_location(unw_cursor, entry->location, NULL); + } + } + return NULL; + } + // Not handled: + default: + return NULL; + } +} + +/** \brief Get the location expression or location list from an attribute + * + * Processes direct expressions as well as location lists. + * + * \param die the DIE + * \param attr the attribute + * \return MC specific representation of the location represented by the given attribute + * of the given die + */ +static dw_location_t MC_dwarf_get_location(mc_object_info_t info, Dwarf_Die* die, Dwarf_Attribute* attr) { + int form = dwarf_whatform(attr); + switch (form) { + + // The attribute is an DWARF location expression: + case DW_FORM_exprloc: + case DW_FORM_block1: // not in the spec + case DW_FORM_block2: + case DW_FORM_block4: + case DW_FORM_block: + { + Dwarf_Op* expr; + size_t len; + if (dwarf_getlocation(attr, &expr, &len)) + xbt_die("Could not read location expression"); + return MC_dwarf_get_expression(expr, len); + } + + // The attribute is a reference to a location list entry: + case DW_FORM_sec_offset: + case DW_FORM_data2: + case DW_FORM_data4: + case DW_FORM_data8: + { + return MC_dwarf_get_location_list(info, die, attr); + } + break; + + default: + xbt_die("Unexpected form %i list for location in attribute %s of <%p>%s", + form, + MC_dwarf_attrname(attr->code), + (void*) dwarf_dieoffset(die), + MC_dwarf_attr_string(die, DW_AT_name)); + return NULL; + } +} + +/** \brief Get the location expression or location list from an attribute + * + * Processes direct expressions as well as location lists. + * + * \param die the DIE + * \param attribute the attribute code + * \return MC specific representation of the location represented by the given attribute + * of the given die + */ +static dw_location_t MC_dwarf_at_location(mc_object_info_t info, Dwarf_Die* die, int attribute) { + if(!dwarf_hasattr_integrate(die, attribute)) + return xbt_new0(s_dw_location_t, 1); + + Dwarf_Attribute attr; + dwarf_attr_integrate(die, attribute, &attr); + return MC_dwarf_get_location(info, die, &attr); +} + +static char* MC_dwarf_at_type(Dwarf_Die* die) { + Dwarf_Attribute attr; + if (dwarf_hasattr_integrate(die, DW_AT_type)) { + dwarf_attr_integrate(die, DW_AT_type, &attr); + Dwarf_Die subtype_die; + if (dwarf_formref_die(&attr, &subtype_die)==NULL) { + xbt_die("Could not find DIE for type"); + } + Dwarf_Off subtype_global_offset = dwarf_dieoffset(&subtype_die); + return bprintf("%" PRIx64 , subtype_global_offset); + } + else return NULL; +} + +static uint64_t MC_dwarf_attr_addr(Dwarf_Die* die, int attribute) { + Dwarf_Attribute attr; + if(dwarf_attr_integrate(die, attribute, &attr)==NULL) + return 0; + Dwarf_Addr value; + if (dwarf_formaddr(&attr, &value) == 0) + return (uint64_t) value; + else + return 0; +} + +static uint64_t MC_dwarf_attr_uint(Dwarf_Die* die, int attribute, uint64_t default_value) { + Dwarf_Attribute attr; + if (dwarf_attr_integrate(die, attribute, &attr)==NULL) + return default_value; + Dwarf_Word value; + return dwarf_formudata(dwarf_attr_integrate(die, attribute, &attr), &value) == 0 ? (uint64_t) value : default_value; +} + +static bool MC_dwarf_attr_flag(Dwarf_Die* die, int attribute, int integrate) { + Dwarf_Attribute attr; + if ((integrate ? dwarf_attr_integrate(die, attribute, &attr) + : dwarf_attr(die, attribute, &attr))==0) + return false; + + bool result; + if (dwarf_formflag(&attr, &result)) + xbt_die("Unexpected form for attribute %s", + MC_dwarf_attrname(attribute)); + return result; +} + +static uint64_t MC_dwarf_default_lower_bound(int lang) { + switch(lang) { + case DW_LANG_C: + case DW_LANG_C89: + case DW_LANG_C99: + case DW_LANG_C_plus_plus: + case DW_LANG_D: + case DW_LANG_Java: + case DW_LANG_ObjC: + case DW_LANG_ObjC_plus_plus: + case DW_LANG_Python: + case DW_LANG_UPC: + return 0; + case DW_LANG_Ada83: + case DW_LANG_Ada95: + case DW_LANG_Fortran77: + case DW_LANG_Fortran90: + case DW_LANG_Fortran95: + case DW_LANG_Modula2: + case DW_LANG_Pascal83: + case DW_LANG_PL1: + case DW_LANG_Cobol74: + case DW_LANG_Cobol85: + return 1; + default: + xbt_die("No default MT_TAG_lower_bound for language %i and none given", lang); + return 0; + } +} + +static uint64_t MC_dwarf_subrange_element_count(Dwarf_Die* die, Dwarf_Die* unit) { + xbt_assert(dwarf_tag(die)==DW_TAG_enumeration_type ||dwarf_tag(die)==DW_TAG_subrange_type, + "MC_dwarf_subrange_element_count called with DIE of type %s", MC_dwarf_die_tagname(die)); + + // Use DW_TAG_count if present: + if (dwarf_hasattr_integrate(die, DW_AT_count)) { + return MC_dwarf_attr_uint(die, DW_AT_count, 0); + } + + // Otherwise compute DW_TAG_upper_bound-DW_TAG_lower_bound + 1: + + if (!dwarf_hasattr_integrate(die, DW_AT_upper_bound)) { + // This is not really 0, but the code expects this (we do not know): + return 0; + } + uint64_t upper_bound = MC_dwarf_attr_uint(die, DW_AT_upper_bound, -1); + + uint64_t lower_bound = 0; + if (dwarf_hasattr_integrate(die, DW_AT_lower_bound)) { + lower_bound = MC_dwarf_attr_uint(die, DW_AT_lower_bound, -1); + } else { + lower_bound = MC_dwarf_default_lower_bound(dwarf_srclang(unit)); + } + return upper_bound - lower_bound + 1; +} + +static uint64_t MC_dwarf_array_element_count(Dwarf_Die* die, Dwarf_Die* unit) { + xbt_assert(dwarf_tag(die)==DW_TAG_array_type, + "MC_dwarf_array_element_count called with DIE of type %s", MC_dwarf_die_tagname(die)); + + int result = 1; + Dwarf_Die child; + int res; + for (res=dwarf_child(die, &child); res==0; res=dwarf_siblingof(&child,&child)) { + int child_tag = dwarf_tag(&child); + if (child_tag==DW_TAG_subrange_type ||child_tag==DW_TAG_enumeration_type) { + result *= MC_dwarf_subrange_element_count(&child, unit); + } + } + return result; +} + +// ***** Location + +Dwarf_Off MC_dwarf_resolve_location(unw_cursor_t* c, dw_location_t location, void* frame_pointer_address) { + unw_word_t res; + switch (location->type){ + case e_dw_compose: + if (xbt_dynar_length(location->location.compose) > 1){ + return 0; /* TODO : location list with optimizations enabled */ + } + dw_location_t location_entry = xbt_dynar_get_as(location->location.compose, 0, dw_location_t); + switch (location_entry->type){ + case e_dw_register: + unw_get_reg(c, location_entry->location.reg, &res); + return res; + case e_dw_bregister_op: + unw_get_reg(c, location_entry->location.breg_op.reg, &res); + return (Dwarf_Off) ((long)res + location_entry->location.breg_op.offset); + break; + case e_dw_fbregister_op: + if (frame_pointer_address != NULL) + return (Dwarf_Off)((char *)frame_pointer_address + location_entry->location.fbreg_op); + else + return 0; + default: + return 0; /* FIXME : implement other cases (with optimizations enabled) */ + } + break; + default: + return 0; + } +} + +// ***** dw_type_t + +static void MC_dwarf_fill_member_location(dw_type_t type, dw_type_t member, Dwarf_Die* child) { + if (dwarf_hasattr(child, DW_AT_data_bit_offset)) { + xbt_die("Can't groke DW_AT_data_bit_offset."); + } + + if (!dwarf_hasattr_integrate(child, DW_AT_data_member_location)) { + if (type->type != DW_TAG_union_type) { + xbt_die( + "Missing DW_AT_data_member_location field in DW_TAG_member %s of type <%p>%s", + member->name, type->id, type->name); + } else { + return; + } + } + + Dwarf_Attribute attr; + dwarf_attr_integrate(child, DW_AT_data_member_location, &attr); + int klass = MC_dwarf_form_get_class(dwarf_whatform(&attr)); + switch (klass) { + case MC_DW_CLASS_EXPRLOC: + case MC_DW_CLASS_BLOCK: + // Location expression: + { + Dwarf_Op* expr; + size_t len; + if (dwarf_getlocation(&attr, &expr, &len)) { + xbt_die( + "Could not read location expression DW_AT_data_member_location in DW_TAG_member %s of type <%p>%s", + MC_dwarf_attr_string(child, DW_AT_name), + type->id, type->name); + } + if (len==1 && expr[0].atom == DW_OP_plus_uconst) { + member->offset = expr[0].number; + } else { + xbt_die("Can't groke this location expression yet."); + } + break; + } + case MC_DW_CLASS_CONSTANT: + // Offset from the base address of the object: + { + Dwarf_Word offset; + if (!dwarf_formudata(&attr, &offset)) + member->offset = offset; + else + xbt_die("Cannot get %s location <%p>%s", + MC_dwarf_attr_string(child, DW_AT_name), + type->id, type->name); + break; + } + case MC_DW_CLASS_LOCLISTPTR: + // Reference to a location list: + // TODO + case MC_DW_CLASS_REFERENCE: + // It's supposed to be possible in DWARF2 but I couldn't find its semantic + // in the spec. + default: + xbt_die("Can't handle form class 0x%x (%i) as DW_AT_member_location", klass, klass); + } + +} + +static void MC_dwarf_add_members(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_type_t type) { + int res; + Dwarf_Die child; + xbt_assert(!type->members); + type->members = xbt_dynar_new(sizeof(dw_type_t), (void(*)(void*))dw_type_free); + for (res=dwarf_child(die, &child); res==0; res=dwarf_siblingof(&child,&child)) { + if (dwarf_tag(&child)==DW_TAG_member) { + // TODO, we should use another type (because is is not a type but a member) + dw_type_t member = xbt_new0(s_dw_type_t, 1); + member->type = -1; + member->id = NULL; + + const char* name = MC_dwarf_attr_string(&child, DW_AT_name); + if(name) + member->name = xbt_strdup(name); + else + member->name = NULL; + + member->byte_size = MC_dwarf_attr_uint(&child, DW_AT_byte_size, 0); + member->element_count = -1; + member->dw_type_id = MC_dwarf_at_type(&child); + member->members = NULL; + member->is_pointer_type = 0; + member->offset = 0; + + if(dwarf_hasattr(&child, DW_AT_data_bit_offset)) { + xbt_die("Can't groke DW_AT_data_bit_offset."); + } + + MC_dwarf_fill_member_location(type, member, &child); + + if (!member->dw_type_id) { + xbt_die("Missing type for member %s of <%p>%s", member->name, type->id, type->name); + } + + xbt_dynar_push(type->members, &member); + } + } +} + +/** \brief Create a MC type object from a DIE + * + * \param info current object info object + * \param DIE (for a given type); + * \param unit compilation unit of the current DIE + * \return MC representation of the type + */ +static dw_type_t MC_dwarf_die_to_type(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit) { + + dw_type_t type = xbt_new0(s_dw_type_t, 1); + type->type = -1; + type->id = NULL; + type->name = NULL; + type->byte_size = 0; + type->element_count = -1; + type->dw_type_id = NULL; + type->members = NULL; + type->is_pointer_type = 0; + type->offset = 0; + + type->type = dwarf_tag(die); + + // Global Offset + type->id = (void *) dwarf_dieoffset(die); + + const char* name = MC_dwarf_attr_string(die, DW_AT_name); + if (name!=NULL) { + type->name = xbt_strdup(name); + } + + XBT_DEBUG("Processing type <%p>%s", type->id, type->name); + + type->dw_type_id = MC_dwarf_at_type(die); + + // Computation of the byte_size; + if (dwarf_hasattr_integrate(die, DW_AT_byte_size)) + type->byte_size = MC_dwarf_attr_uint(die, DW_AT_byte_size, 0); + else if (type->type == DW_TAG_array_type || type->type==DW_TAG_structure_type || type->type==DW_TAG_class_type) { + Dwarf_Word size; + if (dwarf_aggregate_size(die, &size)==0) { + type->byte_size = size; + } + } + + switch (type->type) { + case DW_TAG_array_type: + type->element_count = MC_dwarf_array_element_count(die, unit); + // TODO, handle DW_byte_stride and (not) DW_bit_stride + break; + + case DW_TAG_pointer_type: + case DW_TAG_reference_type: + case DW_TAG_rvalue_reference_type: + type->is_pointer_type = 1; + break; + + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_class_type: + MC_dwarf_add_members(info, die, unit, type); + } + + return type; +} + +static void MC_dwarf_handle_type_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit) { + dw_type_t type = MC_dwarf_die_to_type(info, die, unit); + + char* key = bprintf("%" PRIx64, (uint64_t) type->id); + xbt_dict_set(info->types, key, type, NULL); + + if(type->name && type->byte_size!=0) { + xbt_dict_set(info->types_by_name, type->name, type, NULL); + } +} + +/** \brief Convert libdw location expresion elment into native one (or NULL in some cases) */ +static dw_location_t MC_dwarf_get_expression_element(Dwarf_Op* op) { + dw_location_t element = xbt_new0(s_dw_location_t, 1); + uint8_t atom = op->atom; + if (atom >= DW_OP_reg0 && atom<= DW_OP_reg31) { + element->type = e_dw_register; + element->location.reg = atom - DW_OP_reg0; + } + else if (atom >= DW_OP_breg0 && atom<= DW_OP_breg31) { + element->type = e_dw_bregister_op; + element->location.reg = atom - DW_OP_breg0; + element->location.breg_op.offset = op->number; + } + else if (atom >= DW_OP_lit0 && atom<= DW_OP_lit31) { + element->type = e_dw_lit; + element->location.reg = atom - DW_OP_lit0; + } + else switch (atom) { + case DW_OP_fbreg: + element->type = e_dw_fbregister_op; + element->location.fbreg_op = op->number; + break; + case DW_OP_piece: + element->type = e_dw_piece; + element->location.piece = op->number; + break; + case DW_OP_plus_uconst: + element->type = e_dw_plus_uconst; + element->location.plus_uconst = op->number; + break; + case DW_OP_abs: + element->type = e_dw_arithmetic; + element->location.arithmetic = xbt_strdup("abs"); + break; + case DW_OP_and: + element->type = e_dw_arithmetic; + element->location.arithmetic = xbt_strdup("and"); + break; + case DW_OP_div: + element->type = e_dw_arithmetic; + element->location.arithmetic = xbt_strdup("div"); + break; + case DW_OP_minus: + element->type = e_dw_arithmetic; + element->location.arithmetic = xbt_strdup("minus"); + break; + case DW_OP_mod: + element->type = e_dw_arithmetic; + element->location.arithmetic = xbt_strdup("mod"); + break; + case DW_OP_mul: + element->type = e_dw_arithmetic; + element->location.arithmetic = xbt_strdup("mul"); + break; + case DW_OP_neg: + element->type = e_dw_arithmetic; + element->location.arithmetic = xbt_strdup("neg"); + break; + case DW_OP_not: + element->type = e_dw_arithmetic; + element->location.arithmetic = xbt_strdup("not"); + break; + case DW_OP_or: + element->type = e_dw_arithmetic; + element->location.arithmetic = xbt_strdup("or"); + break; + case DW_OP_plus: + element->type = e_dw_arithmetic; + element->location.arithmetic = xbt_strdup("plus"); + break; + + case DW_OP_stack_value: + // Why nothing here? + xbt_free(element); + return NULL; + + case DW_OP_deref_size: + element->type = e_dw_deref; + element->location.deref_size = (unsigned int short) op->number; + break; + case DW_OP_deref: + element->type = e_dw_deref; + element->location.deref_size = sizeof(void *); + break; + case DW_OP_constu: + element->type = e_dw_uconstant; + element->location.uconstant.bytes = 1; + element->location.uconstant.value = (unsigned long int) op->number; + break; + case DW_OP_consts: + element->type = e_dw_sconstant; + element->location.uconstant.bytes = 1; + element->location.uconstant.value = (unsigned long int) op->number; + break; + + case DW_OP_const1u: + element->type = e_dw_uconstant; + element->location.uconstant.bytes = 1; + element->location.uconstant.value = (unsigned long int) op->number; + break; + case DW_OP_const2u: + element->type = e_dw_uconstant; + element->location.uconstant.bytes = 2; + element->location.uconstant.value = (unsigned long int) op->number; + break; + case DW_OP_const4u: + element->type = e_dw_uconstant; + element->location.uconstant.bytes = 4; + element->location.uconstant.value = (unsigned long int) op->number; + break; + case DW_OP_const8u: + element->type = e_dw_uconstant; + element->location.uconstant.bytes = 8; + element->location.uconstant.value = (unsigned long int) op->number; + break; + + case DW_OP_const1s: + element->type = e_dw_sconstant; + element->location.uconstant.bytes = 1; + element->location.uconstant.value = (unsigned long int) op->number; + break; + case DW_OP_const2s: + element->type = e_dw_sconstant; + element->location.uconstant.bytes = 2; + element->location.uconstant.value = (unsigned long int) op->number; + break; + case DW_OP_const4s: + element->type = e_dw_sconstant; + element->location.uconstant.bytes = 4; + element->location.uconstant.value = (unsigned long int) op->number; + break; + case DW_OP_const8s: + element->type = e_dw_sconstant; + element->location.uconstant.bytes = 8; + element->location.uconstant.value = (unsigned long int) op->number; + break; + default: + element->type = e_dw_unsupported; + break; + } + return element; +} + +/** \brief Convert libdw location expresion into native one */ +static dw_location_t MC_dwarf_get_expression(Dwarf_Op* expr, size_t len) { + dw_location_t loc = xbt_new0(s_dw_location_t, 1); + loc->type = e_dw_compose; + loc->location.compose = xbt_dynar_new(sizeof(dw_location_t), NULL); + + int i; + for (i=0; i!=len; ++i) { + dw_location_t element = MC_dwarf_get_expression_element(expr+i); + if (element) + xbt_dynar_push(loc->location.compose, &element); + } + + return loc; +} + +static int mc_anonymous_variable_index = 0; + +static dw_variable_t MC_die_to_variable(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame) { + // Drop declaration: + if (MC_dwarf_attr_flag(die, DW_AT_declaration, false)) + return NULL; + + Dwarf_Attribute attr_location; + if (dwarf_attr(die, DW_AT_location, &attr_location)==NULL) { + // No location: do not add it ? + return NULL; + } + + dw_variable_t variable = xbt_new0(s_dw_variable_t, 1); + variable->dwarf_offset = dwarf_dieoffset(die); + variable->global = frame == NULL; // Can be override base on DW_AT_location + variable->name = xbt_strdup(MC_dwarf_attr_string(die, DW_AT_name)); + variable->type_origin = MC_dwarf_at_type(die); + + int klass = MC_dwarf_form_get_class(dwarf_whatform(&attr_location)); + switch (klass) { + case MC_DW_CLASS_EXPRLOC: + case MC_DW_CLASS_BLOCK: + // Location expression: + { + Dwarf_Op* expr; + size_t len; + if (dwarf_getlocation(&attr_location, &expr, &len)) { + xbt_die( + "Could not read location expression in DW_AT_location of variable <%p>%s", + (void*) variable->dwarf_offset, variable->name); + } + + if (len==1 && expr[0].atom == DW_OP_addr) { + variable->global = 1; + Dwarf_Off offset = expr[0].number; + // TODO, Why is this different base on the object? + Dwarf_Off base = strcmp(info->file_name, xbt_binary_name) !=0 ? (Dwarf_Off) info->start_exec : 0; + variable->address = (void*) (base + offset); + } else { + variable->location = MC_dwarf_get_expression(expr, len); + } + + break; + } + case MC_DW_CLASS_LOCLISTPTR: + case MC_DW_CLASS_CONSTANT: + // Reference to location list: + variable->location = MC_dwarf_get_location_list(info, die, &attr_location); + break; + default: + xbt_die("Unexpected calss 0x%x (%i) list for location in <%p>%s", + klass, klass, (void*) variable->dwarf_offset, variable->name); + } + + // The current code needs a variable name, + // generate a fake one: + if(!variable->name) { + variable->name = bprintf("@anonymous#%i", mc_anonymous_variable_index++); + } + + return variable; +} + +static void MC_dwarf_handle_variable_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame) { + dw_variable_t variable = MC_die_to_variable(info, die, unit, frame); + if(variable==NULL) + return; + MC_dwarf_register_variable(info, frame, variable); +} + +static void MC_dwarf_handle_subprogram_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t parent_frame) { + dw_frame_t frame = xbt_new0(s_dw_frame_t, 1); + + frame->start = dwarf_dieoffset(die); + + const char* name = MC_dwarf_at_linkage_name(die); + if (name==NULL) + name = MC_dwarf_attr_string(die, DW_AT_name); + frame->name = xbt_strdup(name); + + // This is the base address for DWARF addresses. + // Relocated addresses are offset from this base address. + // See DWARF4 spec 7.5 + void* base = info->flags & MC_OBJECT_INFO_EXECUTABLE ? 0 : MC_object_base_address(info); + + // Variables are filled in the (recursive) call of MC_dwarf_handle_children: + frame->variables = xbt_dynar_new(sizeof(dw_variable_t), dw_variable_free_voidp); + frame->high_pc = ((char*) base) + MC_dwarf_attr_addr(die, DW_AT_high_pc); + frame->low_pc = ((char*) base) + MC_dwarf_attr_addr(die, DW_AT_low_pc); + frame->frame_base = MC_dwarf_at_location(info, die, DW_AT_frame_base); + frame->end = -1; // This one is now useless: + + // Handle children: + MC_dwarf_handle_children(info, die, unit, frame); + + // Register it: + xbt_dict_set(info->local_variables, frame->name, frame, NULL); +} + +static void MC_dwarf_handle_children(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame) { + Dwarf_Die child; + int res; + for (res=dwarf_child(die, &child); res==0; res=dwarf_siblingof(&child,&child)) { + MC_dwarf_handle_die(info, &child, unit, frame); + } +} + +static void MC_dwarf_handle_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame) { + int tag = dwarf_tag(die); + switch (tag) { + case DW_TAG_array_type: + case DW_TAG_class_type: + case DW_TAG_enumeration_type: + case DW_TAG_typedef: + case DW_TAG_pointer_type: + case DW_TAG_string_type: + case DW_TAG_structure_type: + case DW_TAG_subroutine_type: + case DW_TAG_union_type: + case DW_TAG_ptr_to_member_type: + case DW_TAG_set_type: + case DW_TAG_subrange_type: + case DW_TAG_base_type: + case DW_TAG_const_type: + case DW_TAG_file_type: + case DW_TAG_packed_type: + case DW_TAG_volatile_type: + case DW_TAG_restrict_type: + case DW_TAG_interface_type: + case DW_TAG_unspecified_type: + case DW_TAG_mutable_type: + case DW_TAG_shared_type: + MC_dwarf_handle_type_die(info, die, unit); + break; + case DW_TAG_subprogram: + MC_dwarf_handle_subprogram_die(info, die, unit, frame); + return; + // case DW_TAG_formal_parameter: + case DW_TAG_variable: + case DW_TAG_formal_parameter: + MC_dwarf_handle_variable_die(info, die, unit, frame); + break; + } + + // Recursive processing of children DIE: + MC_dwarf_handle_children(info, die, unit, frame); +} + +void MC_dwarf_get_variables(mc_object_info_t info) { + int fd = open(info->file_name, O_RDONLY); + if (fd<0) { + xbt_die("Could not open file %s", info->file_name); + } + Dwarf *dwarf = dwarf_begin(fd, DWARF_C_READ); + if (dwarf==NULL) { + xbt_die("Your program must be compiled with -g"); + } + + Dwarf_Off offset = 0; + Dwarf_Off next_offset = 0; + size_t length; + while (dwarf_nextcu (dwarf, offset, &next_offset, &length, NULL, NULL, NULL) == 0) { + Dwarf_Die die; + + if(dwarf_offdie(dwarf, offset+length, &die)!=NULL) { + + // Skip C++ for now (we will add support for it soon): + int lang = dwarf_srclang(&die); + if((lang==DW_LANG_C_plus_plus) || (lang==DW_LANG_ObjC_plus_plus)) { + offset = next_offset; + continue; + } + + MC_dwarf_handle_die(info, &die, &die, NULL); + } + offset = next_offset; + } + + dwarf_end(dwarf); + close(fd); +} diff --git a/src/mc/mc_dwarf_attrnames.h b/src/mc/mc_dwarf_attrnames.h new file mode 100644 index 0000000000..1ea8182792 --- /dev/null +++ b/src/mc/mc_dwarf_attrnames.h @@ -0,0 +1,139 @@ +case 0x01: return "DW_AT_sibling"; +case 0x02: return "DW_AT_location"; +case 0x03: return "DW_AT_name"; +case 0x09: return "DW_AT_ordering"; +case 0x0a: return "DW_AT_subscr_data"; +case 0x0b: return "DW_AT_byte_size"; +case 0x0c: return "DW_AT_bit_offset"; +case 0x0d: return "DW_AT_bit_size"; +case 0x0f: return "DW_AT_element_list"; +case 0x10: return "DW_AT_stmt_list"; +case 0x11: return "DW_AT_low_pc"; +case 0x12: return "DW_AT_high_pc"; +case 0x13: return "DW_AT_language"; +case 0x14: return "DW_AT_member"; +case 0x15: return "DW_AT_discr"; +case 0x16: return "DW_AT_discr_value"; +case 0x17: return "DW_AT_visibility"; +case 0x18: return "DW_AT_import"; +case 0x19: return "DW_AT_string_length"; +case 0x1a: return "DW_AT_common_reference"; +case 0x1b: return "DW_AT_comp_dir"; +case 0x1c: return "DW_AT_const_value"; +case 0x1d: return "DW_AT_containing_type"; +case 0x1e: return "DW_AT_default_value"; +case 0x20: return "DW_AT_inline"; +case 0x21: return "DW_AT_is_optional"; +case 0x22: return "DW_AT_lower_bound"; +case 0x25: return "DW_AT_producer"; +case 0x27: return "DW_AT_prototyped"; +case 0x2a: return "DW_AT_return_addr"; +case 0x2c: return "DW_AT_start_scope"; +case 0x2e: return "DW_AT_bit_stride"; +case 0x2f: return "DW_AT_upper_bound"; +case 0x31: return "DW_AT_abstract_origin"; +case 0x32: return "DW_AT_accessibility"; +case 0x33: return "DW_AT_address_class"; +case 0x34: return "DW_AT_artificial"; +case 0x35: return "DW_AT_base_types"; +case 0x36: return "DW_AT_calling_convention"; +case 0x37: return "DW_AT_count"; +case 0x38: return "DW_AT_data_member_location"; +case 0x39: return "DW_AT_decl_column"; +case 0x3a: return "DW_AT_decl_file"; +case 0x3b: return "DW_AT_decl_line"; +case 0x3c: return "DW_AT_declaration"; +case 0x3d: return "DW_AT_discr_list"; +case 0x3e: return "DW_AT_encoding"; +case 0x3f: return "DW_AT_external"; +case 0x40: return "DW_AT_frame_base"; +case 0x41: return "DW_AT_friend"; +case 0x42: return "DW_AT_identifier_case"; +case 0x43: return "DW_AT_macro_info"; +case 0x44: return "DW_AT_namelist_item"; +case 0x45: return "DW_AT_priority"; +case 0x46: return "DW_AT_segment"; +case 0x47: return "DW_AT_specification"; +case 0x48: return "DW_AT_static_link"; +case 0x49: return "DW_AT_type"; +case 0x4a: return "DW_AT_use_location"; +case 0x4b: return "DW_AT_variable_parameter"; +case 0x4c: return "DW_AT_virtuality"; +case 0x4d: return "DW_AT_vtable_elem_location"; +case 0x4e: return "DW_AT_allocated"; +case 0x4f: return "DW_AT_associated"; +case 0x50: return "DW_AT_data_location"; +case 0x51: return "DW_AT_byte_stride"; +case 0x52: return "DW_AT_entry_pc"; +case 0x53: return "DW_AT_use_UTF8"; +case 0x54: return "DW_AT_extension"; +case 0x55: return "DW_AT_ranges"; +case 0x56: return "DW_AT_trampoline"; +case 0x57: return "DW_AT_call_column"; +case 0x58: return "DW_AT_call_file"; +case 0x59: return "DW_AT_call_line"; +case 0x5a: return "DW_AT_description"; +case 0x5b: return "DW_AT_binary_scale"; +case 0x5c: return "DW_AT_decimal_scale"; +case 0x5d: return "DW_AT_small"; +case 0x5e: return "DW_AT_decimal_sign"; +case 0x5f: return "DW_AT_digit_count"; +case 0x60: return "DW_AT_picture_string"; +case 0x61: return "DW_AT_mutable"; +case 0x62: return "DW_AT_threads_scaled"; +case 0x63: return "DW_AT_explicit"; +case 0x64: return "DW_AT_object_pointer"; +case 0x65: return "DW_AT_endianity"; +case 0x66: return "DW_AT_elemental"; +case 0x67: return "DW_AT_pure"; +case 0x68: return "DW_AT_recursive"; +case 0x69: return "DW_AT_signature"; +case 0x6a: return "DW_AT_main_subprogram"; +case 0x6b: return "DW_AT_data_bit_offset"; +case 0x6c: return "DW_AT_const_expr"; +case 0x6d: return "DW_AT_enum_class"; +case 0x6e: return "DW_AT_linkage_name"; +case 0x2000: return "DW_AT_lo_user"; +case 0x2001: return "DW_AT_MIPS_fde"; +case 0x2002: return "DW_AT_MIPS_loop_begin"; +case 0x2003: return "DW_AT_MIPS_tail_loop_begin"; +case 0x2004: return "DW_AT_MIPS_epilog_begin"; +case 0x2005: return "DW_AT_MIPS_loop_unroll_factor"; +case 0x2006: return "DW_AT_MIPS_software_pipeline_depth"; +case 0x2007: return "DW_AT_MIPS_linkage_name"; +case 0x2008: return "DW_AT_MIPS_stride"; +case 0x2009: return "DW_AT_MIPS_abstract_name"; +case 0x200a: return "DW_AT_MIPS_clone_origin"; +case 0x200b: return "DW_AT_MIPS_has_inlines"; +case 0x200c: return "DW_AT_MIPS_stride_byte"; +case 0x200d: return "DW_AT_MIPS_stride_elem"; +case 0x200e: return "DW_AT_MIPS_ptr_dopetype"; +case 0x200f: return "DW_AT_MIPS_allocatable_dopetype"; +case 0x2010: return "DW_AT_MIPS_assumed_shape_dopetype"; +case 0x2011: return "DW_AT_MIPS_assumed_size"; +case 0x2101: return "DW_AT_sf_names"; +case 0x2102: return "DW_AT_src_info"; +case 0x2103: return "DW_AT_mac_info"; +case 0x2104: return "DW_AT_src_coords"; +case 0x2105: return "DW_AT_body_begin"; +case 0x2106: return "DW_AT_body_end"; +case 0x2107: return "DW_AT_GNU_vector"; +case 0x2108: return "DW_AT_GNU_guarded_by"; +case 0x2109: return "DW_AT_GNU_pt_guarded_by"; +case 0x210a: return "DW_AT_GNU_guarded"; +case 0x210b: return "DW_AT_GNU_pt_guarded"; +case 0x210c: return "DW_AT_GNU_locks_excluded"; +case 0x210d: return "DW_AT_GNU_exclusive_locks_required"; +case 0x210e: return "DW_AT_GNU_shared_locks_required"; +case 0x210f: return "DW_AT_GNU_odr_signature"; +case 0x2110: return "DW_AT_GNU_template_name"; +case 0x2111: return "DW_AT_GNU_call_site_value"; +case 0x2112: return "DW_AT_GNU_call_site_data_value"; +case 0x2113: return "DW_AT_GNU_call_site_target"; +case 0x2114: return "DW_AT_GNU_call_site_target_clobbered"; +case 0x2115: return "DW_AT_GNU_tail_call"; +case 0x2116: return "DW_AT_GNU_all_tail_call_sites"; +case 0x2117: return "DW_AT_GNU_all_call_sites"; +case 0x2118: return "DW_AT_GNU_all_source_call_sites"; +case 0x2119: return "DW_AT_GNU_macros"; +case 0x3fff: return "DW_AT_hi_user"; diff --git a/src/mc/mc_dwarf_tagnames.h b/src/mc/mc_dwarf_tagnames.h new file mode 100644 index 0000000000..98b883a395 --- /dev/null +++ b/src/mc/mc_dwarf_tagnames.h @@ -0,0 +1,74 @@ +case 0x01: return "DW_TAG_array_type"; +case 0x02: return "DW_TAG_class_type"; +case 0x03: return "DW_TAG_entry_point"; +case 0x04: return "DW_TAG_enumeration_type"; +case 0x05: return "DW_TAG_formal_parameter"; +case 0x08: return "DW_TAG_imported_declaration"; +case 0x0a: return "DW_TAG_label"; +case 0x0b: return "DW_TAG_lexical_block"; +case 0x0d: return "DW_TAG_member"; +case 0x0f: return "DW_TAG_pointer_type"; +case 0x10: return "DW_TAG_reference_type"; +case 0x11: return "DW_TAG_compile_unit"; +case 0x12: return "DW_TAG_string_type"; +case 0x13: return "DW_TAG_structure_type"; +case 0x15: return "DW_TAG_subroutine_type"; +case 0x16: return "DW_TAG_typedef"; +case 0x17: return "DW_TAG_union_type"; +case 0x18: return "DW_TAG_unspecified_parameters"; +case 0x19: return "DW_TAG_variant"; +case 0x1a: return "DW_TAG_common_block"; +case 0x1b: return "DW_TAG_common_inclusion"; +case 0x1c: return "DW_TAG_inheritance"; +case 0x1d: return "DW_TAG_inlined_subroutine"; +case 0x1e: return "DW_TAG_module"; +case 0x1f: return "DW_TAG_ptr_to_member_type"; +case 0x20: return "DW_TAG_set_type"; +case 0x21: return "DW_TAG_subrange_type"; +case 0x22: return "DW_TAG_with_stmt"; +case 0x23: return "DW_TAG_access_declaration"; +case 0x24: return "DW_TAG_base_type"; +case 0x25: return "DW_TAG_catch_block"; +case 0x26: return "DW_TAG_const_type"; +case 0x27: return "DW_TAG_constant"; +case 0x28: return "DW_TAG_enumerator"; +case 0x29: return "DW_TAG_file_type"; +case 0x2a: return "DW_TAG_friend"; +case 0x2b: return "DW_TAG_namelist"; +case 0x2c: return "DW_TAG_namelist_item"; +case 0x2d: return "DW_TAG_packed_type"; +case 0x2e: return "DW_TAG_subprogram"; +case 0x2f: return "DW_TAG_template_type_parameter"; +case 0x30: return "DW_TAG_template_value_parameter"; +case 0x31: return "DW_TAG_thrown_type"; +case 0x32: return "DW_TAG_try_block"; +case 0x33: return "DW_TAG_variant_part"; +case 0x34: return "DW_TAG_variable"; +case 0x35: return "DW_TAG_volatile_type"; +case 0x36: return "DW_TAG_dwarf_procedure"; +case 0x37: return "DW_TAG_restrict_type"; +case 0x38: return "DW_TAG_interface_type"; +case 0x39: return "DW_TAG_namespace"; +case 0x3a: return "DW_TAG_imported_module"; +case 0x3b: return "DW_TAG_unspecified_type"; +case 0x3c: return "DW_TAG_partial_unit"; +case 0x3d: return "DW_TAG_imported_unit"; +case 0x3e: return "DW_TAG_mutable_type"; +case 0x3f: return "DW_TAG_condition"; +case 0x40: return "DW_TAG_shared_type"; +case 0x41: return "DW_TAG_type_unit"; +case 0x42: return "DW_TAG_rvalue_reference_type"; +case 0x43: return "DW_TAG_template_alias"; +case 0x4080: return "DW_TAG_lo_user"; +case 0x4081: return "DW_TAG_MIPS_loop"; +case 0x4101: return "DW_TAG_format_label"; +case 0x4102: return "DW_TAG_function_template"; +case 0x4103: return "DW_TAG_class_template"; +case 0x4104: return "DW_TAG_GNU_BINCL"; +case 0x4105: return "DW_TAG_GNU_EINCL"; +case 0x4106: return "DW_TAG_GNU_template_template_param"; +case 0x4107: return "DW_TAG_GNU_template_parameter_pack"; +case 0x4108: return "DW_TAG_GNU_formal_parameter_pack"; +case 0x4109: return "DW_TAG_GNU_call_site"; +case 0x410a: return "DW_TAG_GNU_call_site_parameter"; +case 0xffff: return "DW_TAG_hi_user"; diff --git a/src/mc/mc_global.c b/src/mc/mc_global.c index 16ebebe384..0cda77fb7f 100644 --- a/src/mc/mc_global.c +++ b/src/mc/mc_global.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "simgrid/sg_config.h" #include "../surf/surf_private.h" @@ -29,9 +30,11 @@ 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; +int _sg_mc_comms_determinism=0; int user_max_depth_reached = 0; @@ -69,6 +72,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."); @@ -90,6 +100,13 @@ void _mc_cfg_cb_dot_output(const char *name, int pos) { _sg_mc_dot_output_file= xbt_cfg_get_string(_sg_cfg_set, name); } +void _mc_cfg_cb_comms_determinism(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 detection of determinism in the communications schemes 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."); + } + _sg_mc_comms_determinism= xbt_cfg_get_boolean(_sg_cfg_set, name); +} + /* MC global data structures */ mc_state_t mc_current_state = NULL; char mc_replay_mode = FALSE; @@ -110,16 +127,10 @@ int compare; xbt_automaton_t _mc_property_automaton = NULL; /* Variables */ -xbt_dict_t mc_local_variables_libsimgrid = NULL; -xbt_dict_t mc_local_variables_binary = NULL; -xbt_dynar_t mc_global_variables_libsimgrid = NULL; -xbt_dynar_t mc_global_variables_binary = NULL; -xbt_dict_t mc_variables_type_libsimgrid = NULL; -xbt_dict_t mc_variables_type_binary = NULL; +mc_object_info_t mc_libsimgrid_info = NULL; +mc_object_info_t mc_binary_info = NULL; /* Ignore mechanism */ -xbt_dynar_t mc_stack_comparison_ignore; -xbt_dynar_t mc_data_bss_comparison_ignore; extern xbt_dynar_t mc_heap_comparison_ignore; extern xbt_dynar_t stacks_areas; @@ -151,7 +162,7 @@ static void dw_location_entry_free(dw_location_entry_t e){ xbt_free(e); } -static void dw_type_free(dw_type_t t){ +void dw_type_free(dw_type_t t){ xbt_free(t->name); xbt_free(t->dw_type_id); xbt_dynar_free(&(t->members)); @@ -162,20 +173,169 @@ static void dw_type_free_voidp(void *t){ dw_type_free((dw_type_t) * (void **) t); } -static void dw_variable_free(dw_variable_t v){ +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->address.location); + dw_location_free(v->location); xbt_free(v); } } -static void dw_variable_free_voidp(void *t){ +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){ @@ -314,110 +474,10 @@ static dw_location_t MC_dwarf_get_location(xbt_dict_t location_list, char *expr) } -static xbt_dict_t MC_dwarf_get_location_list(const char *elf_file){ - - char *command = bprintf("objdump -Wo %s", elf_file); - - FILE *fp = popen(command, "r"); - - if(fp == NULL){ - perror("popen for objdump failed"); - xbt_abort(); - } - - int debug = 0; /*Detect if the program has been compiled with -g */ - - xbt_dict_t location_list = xbt_dict_new_homogeneous(NULL); - char *line = NULL, *loc_expr = NULL; - ssize_t read; - size_t n = 0; - int cursor_remove; - xbt_dynar_t split = NULL; - - while ((read = xbt_getline(&line, &n, fp)) != -1) { - - /* Wipeout the new line character */ - line[read - 1] = '\0'; - - xbt_str_trim(line, NULL); - - if(n == 0) - continue; - - if(strlen(line) == 0) - continue; - - if(debug == 0){ - - if(strncmp(line, elf_file, strlen(elf_file)) == 0) - continue; - - if(strncmp(line, "Contents", 8) == 0) - continue; - - if(strncmp(line, "Offset", 6) == 0){ - debug = 1; - continue; - } - } - - if(debug == 0){ - XBT_INFO("Your program must be compiled with -g"); - xbt_abort(); - } - - xbt_dynar_t loclist = xbt_dynar_new(sizeof(dw_location_entry_t), NULL); - - xbt_str_strip_spaces(line); - split = xbt_str_split(line, " "); - - while(read != -1 && strcmp("lowpc = strtoul((char *)xbt_dynar_get_as(split, 1, char *), NULL, 16); - new_entry->highpc = strtoul((char *)xbt_dynar_get_as(split, 2, char *), NULL, 16); - - cursor_remove =0; - while(cursor_remove < 3){ - xbt_dynar_remove_at(split, 0, NULL); - cursor_remove++; - } - - loc_expr = xbt_str_join(split, " "); - xbt_str_ltrim(loc_expr, "("); - xbt_str_rtrim(loc_expr, ")"); - new_entry->location = MC_dwarf_get_location(NULL, loc_expr); - - xbt_dynar_push(loclist, &new_entry); - - xbt_dynar_free(&split); - free(loc_expr); - - read = xbt_getline(&line, &n, fp); - if(read != -1){ - line[read - 1] = '\0'; - xbt_str_strip_spaces(line); - split = xbt_str_split(line, " "); - } - - } - - - char *key = bprintf("%lu", strtoul((char *)xbt_dynar_get_as(split, 0, char *), NULL, 16)); - xbt_dict_set(location_list, key, loclist, NULL); - xbt_free(key); - - xbt_dynar_free(&split); - - } - - xbt_free(line); - xbt_free(command); - pclose(fp); - - return location_list; -} - +/** \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; @@ -468,9 +528,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; @@ -481,7 +541,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; @@ -492,729 +552,28 @@ 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); + if (index != -1) + xbt_dynar_insert_at(info->global_variables, index, &variable); + // TODO, else ? +} -static void MC_dwarf_get_variables(const char *elf_file, xbt_dict_t location_list, xbt_dict_t *local_variables, xbt_dynar_t *global_variables, xbt_dict_t *types){ - - char *command = bprintf("objdump -Wi %s", elf_file); - - FILE *fp = popen(command, "r"); - - if(fp == NULL) - perror("popen for objdump failed"); - - char *line = NULL, *origin, *abstract_origin, *current_frame = NULL, - *subprogram_name = NULL, *subprogram_start = NULL, *subprogram_end = NULL, - *node_type = NULL, *location_type = NULL, *variable_name = NULL, - *loc_expr = NULL, *name = NULL, *end =NULL, *type_origin = NULL, *global_address = NULL, - *parent_value = NULL; - - ssize_t read =0; - size_t n = 0; - int global_variable = 0, parent = 0, new_frame = 0, new_variable = 1, size = 0, - is_pointer = 0, struct_decl = 0, member_end = 0, - enumeration_size = 0, subrange = 0, union_decl = 0, offset = 0, index = 0; - - xbt_dynar_t split = NULL, split2 = NULL; - - xbt_dict_t variables_origin = xbt_dict_new_homogeneous(xbt_free); - xbt_dict_t subprograms_origin = xbt_dict_new_homogeneous(xbt_free); - - dw_frame_t variable_frame, subroutine_frame = NULL; - - e_dw_type_type type_type = -1; - - read = xbt_getline(&line, &n, fp); - - while (read != -1) { - - /* Wipeout the new line character */ - line[read - 1] = '\0'; - - if(n == 0 || strlen(line) == 0){ - read = xbt_getline(&line, &n, fp); - continue; - } - - xbt_str_ltrim(line, NULL); - xbt_str_strip_spaces(line); - - if(line[0] != '<'){ - read = xbt_getline(&line, &n, fp); - continue; - } - - xbt_dynar_free(&split); - split = xbt_str_split(line, " "); - - /* Get node type */ - node_type = xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *); - - if(strcmp(node_type, "(DW_TAG_subprogram)") == 0){ /* New frame */ - - dw_frame_t frame = NULL; - - strtok(xbt_dynar_get_as(split, 0, char *), "<"); - subprogram_start = xbt_strdup(strtok(NULL, "<")); - xbt_str_rtrim(subprogram_start, ">:"); - - read = xbt_getline(&line, &n, fp); - - while(read != -1){ - - /* Wipeout the new line character */ - line[read - 1] = '\0'; - - if(n == 0 || strlen(line) == 0){ - read = xbt_getline(&line, &n, fp); - continue; - } - - xbt_dynar_free(&split); - xbt_str_rtrim(line, NULL); - xbt_str_strip_spaces(line); - split = xbt_str_split(line, " "); - - node_type = xbt_dynar_get_as(split, 1, char *); - - if(strncmp(node_type, "DW_AT_", 6) != 0) - break; - - if(strcmp(node_type, "DW_AT_sibling") == 0){ - - subprogram_end = xbt_strdup(xbt_dynar_get_as(split, 3, char*)); - xbt_str_ltrim(subprogram_end, "<0x"); - xbt_str_rtrim(subprogram_end, ">"); - - }else if(strcmp(node_type, "DW_AT_abstract_origin:") == 0){ /* Frame already in dict */ - - new_frame = 0; - abstract_origin = xbt_strdup(xbt_dynar_get_as(split, 2, char*)); - xbt_str_ltrim(abstract_origin, "<0x"); - xbt_str_rtrim(abstract_origin, ">"); - subprogram_name = (char *)xbt_dict_get_or_null(subprograms_origin, abstract_origin); - frame = xbt_dict_get_or_null(*local_variables, subprogram_name); - xbt_free(abstract_origin); - - }else if(strcmp(node_type, "DW_AT_name") == 0){ - - new_frame = 1; - xbt_free(current_frame); - frame = xbt_new0(s_dw_frame_t, 1); - frame->name = strdup(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *)); - frame->variables = xbt_dynar_new(sizeof(dw_variable_t), dw_variable_free_voidp); - frame->frame_base = xbt_new0(s_dw_location_t, 1); - current_frame = strdup(frame->name); - - xbt_dict_set(subprograms_origin, subprogram_start, xbt_strdup(frame->name), NULL); - - }else if(strcmp(node_type, "DW_AT_frame_base") == 0){ - - location_type = xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *); - - if(strcmp(location_type, "list)") == 0){ /* Search location in location list */ - - frame->frame_base = MC_dwarf_get_location(location_list, xbt_dynar_get_as(split, 3, char *)); - - }else{ - - xbt_str_strip_spaces(line); - split2 = xbt_str_split(line, "("); - xbt_dynar_remove_at(split2, 0, NULL); - loc_expr = xbt_str_join(split2, " "); - xbt_str_rtrim(loc_expr, ")"); - frame->frame_base = MC_dwarf_get_location(NULL, loc_expr); - xbt_dynar_free(&split2); - xbt_free(loc_expr); - - } - - }else if(strcmp(node_type, "DW_AT_low_pc") == 0){ - - if(frame != NULL) - frame->low_pc = (void *)strtoul(xbt_dynar_get_as(split, 3, char *), NULL, 16); - - }else if(strcmp(node_type, "DW_AT_high_pc") == 0){ - - if(frame != NULL) - frame->high_pc = (void *)strtoul(xbt_dynar_get_as(split, 3, char *), NULL, 16); - - }else if(strcmp(node_type, "DW_AT_MIPS_linkage_name:") == 0){ - - xbt_free(frame->name); - xbt_free(current_frame); - frame->name = strdup(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *)); - current_frame = strdup(frame->name); - xbt_dict_set(subprograms_origin, subprogram_start, xbt_strdup(frame->name), NULL); - - } - - read = xbt_getline(&line, &n, fp); - - } - - if(new_frame == 1){ - frame->start = strtoul(subprogram_start, NULL, 16); - if(subprogram_end != NULL) - frame->end = strtoul(subprogram_end, NULL, 16); - xbt_dict_set(*local_variables, frame->name, frame, NULL); - } - - xbt_free(subprogram_start); - xbt_free(subprogram_end); - subprogram_end = NULL; - - - }else if(strcmp(node_type, "(DW_TAG_variable)") == 0){ /* New variable */ - - dw_variable_t var = NULL; - - parent_value = strdup(xbt_dynar_get_as(split, 0, char *)); - parent_value = strtok(parent_value,"<"); - xbt_str_rtrim(parent_value, ">"); - parent = atoi(parent_value); - xbt_free(parent_value); - - if(parent == 1) - global_variable = 1; - - strtok(xbt_dynar_get_as(split, 0, char *), "<"); - origin = xbt_strdup(strtok(NULL, "<")); - xbt_str_rtrim(origin, ">:"); - - read = xbt_getline(&line, &n, fp); - - while(read != -1){ - - /* Wipeout the new line character */ - line[read - 1] = '\0'; - - if(n == 0 || strlen(line) == 0){ - read = xbt_getline(&line, &n, fp); - continue; - } - - xbt_dynar_free(&split); - xbt_str_rtrim(line, NULL); - xbt_str_strip_spaces(line); - split = xbt_str_split(line, " "); - - node_type = xbt_dynar_get_as(split, 1, char *); - - if(strncmp(node_type, "DW_AT_", 6) != 0) - break; - - if(strcmp(node_type, "DW_AT_name") == 0){ - - var = xbt_new0(s_dw_variable_t, 1); - var->name = xbt_strdup(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *)); - xbt_dict_set(variables_origin, origin, xbt_strdup(var->name), NULL); - - }else if(strcmp(node_type, "DW_AT_abstract_origin:") == 0){ - - new_variable = 0; - - abstract_origin = xbt_dynar_get_as(split, 2, char *); - xbt_str_ltrim(abstract_origin, "<0x"); - xbt_str_rtrim(abstract_origin, ">"); - - variable_name = (char *)xbt_dict_get_or_null(variables_origin, abstract_origin); - variable_frame = MC_dwarf_get_frame_by_offset(*local_variables, strtoul(abstract_origin, NULL, 16)); - var = MC_dwarf_get_variable_by_name(variable_frame, variable_name); - - }else if(strcmp(node_type, "DW_AT_location") == 0){ - - if(var != NULL){ - - if(!global_variable){ - - location_type = xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *); - - if(strcmp(location_type, "list)") == 0){ /* Search location in location list */ - var->address.location = MC_dwarf_get_location(location_list, xbt_dynar_get_as(split, 3, char *)); - }else{ - xbt_str_strip_spaces(line); - split2 = xbt_str_split(line, "("); - xbt_dynar_remove_at(split2, 0, NULL); - loc_expr = xbt_str_join(split2, " "); - xbt_str_rtrim(loc_expr, ")"); - if(strncmp("DW_OP_addr", loc_expr, 10) == 0){ - global_variable = 1; - xbt_dynar_free(&split2); - split2 = xbt_str_split(loc_expr, " "); - if(strcmp(elf_file, xbt_binary_name) != 0) - var->address.address = (char *)start_text_libsimgrid + strtoul(xbt_dynar_get_as(split2, xbt_dynar_length(split2) - 1, char*), NULL, 16); - else - var->address.address = (void *)strtoul(xbt_dynar_get_as(split2, xbt_dynar_length(split2) - 1, char*), NULL, 16); - }else{ - var->address.location = MC_dwarf_get_location(NULL, loc_expr); - } - xbt_dynar_free(&split2); - xbt_free(loc_expr); - } - }else{ - global_address = xbt_strdup(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *)); - xbt_str_rtrim(global_address, ")"); - if(strcmp(elf_file, xbt_binary_name) != 0) - var->address.address = (char *)start_text_libsimgrid + strtoul(global_address, NULL, 16); - else - var->address.address = (void *)strtoul(global_address, NULL, 16); - xbt_free(global_address); - global_address = NULL; - } - - } - - }else if(strcmp(node_type, "DW_AT_type") == 0){ - - type_origin = xbt_strdup(xbt_dynar_get_as(split, 3, char *)); - xbt_str_ltrim(type_origin, "<0x"); - xbt_str_rtrim(type_origin, ">"); - - }else if(strcmp(node_type, "DW_AT_declaration") == 0){ - - new_variable = 0; - if(new_variable){ - dw_variable_free(var); - var = NULL; - } - - }else if(strcmp(node_type, "DW_AT_artificial") == 0){ - - new_variable = 0; - if(new_variable){ - dw_variable_free(var); - var = NULL; - } - - } - - read = xbt_getline(&line, &n, fp); - - } - - if(new_variable == 1){ - - if(!global_variable){ - variable_frame = xbt_dict_get_or_null(*local_variables, current_frame); - var->type_origin = strdup(type_origin); - var->global = 0; - index = MC_dwarf_get_variable_index(variable_frame->variables, var->name, NULL); - if(index != -1) - xbt_dynar_insert_at(variable_frame->variables, index, &var); - }else{ - var->type_origin = strdup(type_origin); - var->global = 1; - index = MC_dwarf_get_variable_index(*global_variables, var->name, var->address.address); - if(index != -1) - xbt_dynar_insert_at(*global_variables, index, &var); - } - - xbt_free(type_origin); - type_origin = NULL; - } - - global_variable = 0; - new_variable = 1; - - }else if(strcmp(node_type, "(DW_TAG_inlined_subroutine)") == 0){ - - read = xbt_getline(&line, &n, fp); - - while(read != -1){ - - /* Wipeout the new line character */ - line[read - 1] = '\0'; - - if(n == 0 || strlen(line) == 0){ - read = xbt_getline(&line, &n, fp); - continue; - } - - xbt_dynar_free(&split); - xbt_str_rtrim(line, NULL); - xbt_str_strip_spaces(line); - split = xbt_str_split(line, " "); - - if(strncmp(xbt_dynar_get_as(split, 1, char *), "DW_AT_", 6) != 0) - break; - - node_type = xbt_dynar_get_as(split, 1, char *); - - if(strcmp(node_type, "DW_AT_abstract_origin:") == 0){ - - origin = xbt_dynar_get_as(split, 2, char *); - xbt_str_ltrim(origin, "<0x"); - xbt_str_rtrim(origin, ">"); - - subprogram_name = (char *)xbt_dict_get_or_null(subprograms_origin, origin); - subroutine_frame = xbt_dict_get_or_null(*local_variables, subprogram_name); - - }else if(strcmp(node_type, "DW_AT_low_pc") == 0){ - - subroutine_frame->low_pc = (void *)strtoul(xbt_dynar_get_as(split, 3, char *), NULL, 16); - - }else if(strcmp(node_type, "DW_AT_high_pc") == 0){ - - subroutine_frame->high_pc = (void *)strtoul(xbt_dynar_get_as(split, 3, char *), NULL, 16); - } - - read = xbt_getline(&line, &n, fp); - - } - - }else if(strcmp(node_type, "(DW_TAG_base_type)") == 0 - || strcmp(node_type, "(DW_TAG_enumeration_type)") == 0 - || strcmp(node_type, "(DW_TAG_enumerator)") == 0 - || strcmp(node_type, "(DW_TAG_typedef)") == 0 - || strcmp(node_type, "(DW_TAG_const_type)") == 0 - || strcmp(node_type, "(DW_TAG_subroutine_type)") == 0 - || strcmp(node_type, "(DW_TAG_volatile_type)") == 0 - || (is_pointer = !strcmp(node_type, "(DW_TAG_pointer_type)"))){ - - if(strcmp(node_type, "(DW_TAG_base_type)") == 0) - type_type = e_dw_base_type; - else if(strcmp(node_type, "(DW_TAG_enumeration_type)") == 0) - type_type = e_dw_enumeration_type; - else if(strcmp(node_type, "(DW_TAG_enumerator)") == 0) - type_type = e_dw_enumerator; - else if(strcmp(node_type, "(DW_TAG_typedef)") == 0) - type_type = e_dw_typedef; - else if(strcmp(node_type, "(DW_TAG_const_type)") == 0) - type_type = e_dw_const_type; - else if(strcmp(node_type, "(DW_TAG_pointer_type)") == 0) - type_type = e_dw_pointer_type; - else if(strcmp(node_type, "(DW_TAG_subroutine_type)") == 0) - type_type = e_dw_subroutine_type; - else if(strcmp(node_type, "(DW_TAG_volatile_type)") == 0) - type_type = e_dw_volatile_type; - - strtok(xbt_dynar_get_as(split, 0, char *), "<"); - origin = strdup(strtok(NULL, "<")); - xbt_str_rtrim(origin, ">:"); - - read = xbt_getline(&line, &n, fp); - - while(read != -1){ - - /* Wipeout the new line character */ - line[read - 1] = '\0'; - - if(n == 0 || strlen(line) == 0){ - read = xbt_getline(&line, &n, fp); - continue; - } - - xbt_dynar_free(&split); - xbt_str_rtrim(line, NULL); - xbt_str_strip_spaces(line); - split = xbt_str_split(line, " "); - - if(strncmp(xbt_dynar_get_as(split, 1, char *), "DW_AT_", 6) != 0) - break; - - node_type = xbt_dynar_get_as(split, 1, char *); - - if(strcmp(node_type, "DW_AT_byte_size") == 0){ - size = strtol(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char*), NULL, 10); - if(type_type == e_dw_enumeration_type) - enumeration_size = size; - }else if(strcmp(node_type, "DW_AT_name") == 0){ - end = xbt_str_join(split, " "); - xbt_dynar_free(&split); - split = xbt_str_split(end, "):"); - xbt_str_ltrim(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char*), NULL); - name = xbt_strdup(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char*)); - }else if(strcmp(node_type, "DW_AT_type") == 0){ - type_origin = xbt_strdup(xbt_dynar_get_as(split, 3, char *)); - xbt_str_ltrim(type_origin, "<0x"); - xbt_str_rtrim(type_origin, ">"); - } - - read = xbt_getline(&line, &n, fp); - } - - dw_type_t type = xbt_new0(s_dw_type_t, 1); - type->type = type_type; - if(name) - type->name = xbt_strdup(name); - else - type->name = xbt_strdup("undefined"); - type->is_pointer_type = is_pointer; - type->id = (void *)strtoul(origin, NULL, 16); - if(type_origin) - type->dw_type_id = xbt_strdup(type_origin); - if(type_type == e_dw_enumerator) - type->size = enumeration_size; - else - type->size = size; - type->members = NULL; - - xbt_dict_set(*types, origin, type, NULL); - - xbt_free(name); - name = NULL; - xbt_free(type_origin); - type_origin = NULL; - xbt_free(end); - end = NULL; - - is_pointer = 0; - size = 0; - xbt_free(origin); - - }else if(strcmp(node_type, "(DW_TAG_structure_type)") == 0 || strcmp(node_type, "(DW_TAG_union_type)") == 0){ - - if(strcmp(node_type, "(DW_TAG_structure_type)") == 0) - struct_decl = 1; - else - union_decl = 1; - - strtok(xbt_dynar_get_as(split, 0, char *), "<"); - origin = strdup(strtok(NULL, "<")); - xbt_str_rtrim(origin, ">:"); - - read = xbt_getline(&line, &n, fp); - - dw_type_t type = NULL; - - while(read != -1){ - - while(read != -1){ - - /* Wipeout the new line character */ - line[read - 1] = '\0'; - - if(n == 0 || strlen(line) == 0){ - read = xbt_getline(&line, &n, fp); - continue; - } - - xbt_dynar_free(&split); - xbt_str_rtrim(line, NULL); - xbt_str_strip_spaces(line); - split = xbt_str_split(line, " "); - - node_type = xbt_dynar_get_as(split, 1, char *); - - if(strncmp(node_type, "DW_AT_", 6) != 0){ - member_end = 1; - break; - } - - if(strcmp(node_type, "DW_AT_byte_size") == 0){ - size = strtol(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char*), NULL, 10); - }else if(strcmp(node_type, "DW_AT_name") == 0){ - xbt_free(end); - end = xbt_str_join(split, " "); - xbt_dynar_free(&split); - split = xbt_str_split(end, "):"); - xbt_str_ltrim(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char*), NULL); - name = xbt_strdup(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char*)); - }else if(strcmp(node_type, "DW_AT_type") == 0){ - type_origin = xbt_strdup(xbt_dynar_get_as(split, 3, char *)); - xbt_str_ltrim(type_origin, "<0x"); - xbt_str_rtrim(type_origin, ">"); - }else if(strcmp(node_type, "DW_AT_data_member_location:") == 0){ - xbt_free(end); - end = xbt_str_join(split, " "); - xbt_dynar_free(&split); - split = xbt_str_split(end, "DW_OP_plus_uconst:"); - xbt_str_ltrim(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *), NULL); - xbt_str_rtrim(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *), ")"); - offset = strtol(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char*), NULL, 10); - } - - read = xbt_getline(&line, &n, fp); - - } - - if(member_end && type){ - member_end = 0; - - dw_type_t member_type = xbt_new0(s_dw_type_t, 1); - member_type->name = xbt_strdup(name); - member_type->size = size; - member_type->is_pointer_type = is_pointer; - member_type->id = (void *)strtoul(origin, NULL, 16); - member_type->offset = offset; - if(type_origin) - member_type->dw_type_id = xbt_strdup(type_origin); - - xbt_dynar_push(type->members, &member_type); - - xbt_free(name); - name = NULL; - xbt_free(end); - end = NULL; - xbt_free(type_origin); - type_origin = NULL; - size = 0; - offset = 0; - - xbt_free(origin); - origin = NULL; - strtok(xbt_dynar_get_as(split, 0, char *), "<"); - origin = strdup(strtok(NULL, "<")); - xbt_str_rtrim(origin, ">:"); - - } - - if(struct_decl || union_decl){ - type = xbt_new0(s_dw_type_t, 1); - if(struct_decl) - type->type = e_dw_structure_type; - else - type->type = e_dw_union_type; - type->name = xbt_strdup(name); - type->size = size; - type->is_pointer_type = is_pointer; - type->id = (void *)strtoul(origin, NULL, 16); - if(type_origin) - type->dw_type_id = xbt_strdup(type_origin); - type->members = xbt_dynar_new(sizeof(dw_type_t), dw_type_free_voidp); - - xbt_dict_set(*types, origin, type, NULL); - - xbt_free(name); - name = NULL; - xbt_free(end); - end = NULL; - xbt_free(type_origin); - type_origin = NULL; - size = 0; - struct_decl = 0; - union_decl = 0; - - } - - if(strcmp(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *), "(DW_TAG_member)") != 0) - break; - - read = xbt_getline(&line, &n, fp); - - } - - xbt_free(origin); - origin = NULL; - - }else if(strcmp(node_type, "(DW_TAG_array_type)") == 0){ - - strtok(xbt_dynar_get_as(split, 0, char *), "<"); - origin = strdup(strtok(NULL, "<")); - xbt_str_rtrim(origin, ">:"); - - read = xbt_getline(&line, &n, fp); - - dw_type_t type = NULL; - - while(read != -1){ - - while(read != -1){ - - /* Wipeout the new line character */ - line[read - 1] = '\0'; - - if(n == 0 || strlen(line) == 0){ - read = xbt_getline(&line, &n, fp); - continue; - } - - xbt_dynar_free(&split); - xbt_str_rtrim(line, NULL); - xbt_str_strip_spaces(line); - split = xbt_str_split(line, " "); - - node_type = xbt_dynar_get_as(split, 1, char *); - - if(strncmp(node_type, "DW_AT_", 6) != 0) - break; - - if(strcmp(node_type, "DW_AT_upper_bound") == 0){ - size = strtol(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char*), NULL, 10); - }else if(strcmp(node_type, "DW_AT_name") == 0){ - end = xbt_str_join(split, " "); - xbt_dynar_free(&split); - split = xbt_str_split(end, "):"); - xbt_str_ltrim(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char*), NULL); - name = xbt_strdup(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char*)); - }else if(strcmp(node_type, "DW_AT_type") == 0){ - type_origin = xbt_strdup(xbt_dynar_get_as(split, 3, char *)); - xbt_str_ltrim(type_origin, "<0x"); - xbt_str_rtrim(type_origin, ">"); - } - - read = xbt_getline(&line, &n, fp); - - } - - if(strcmp(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *), "(DW_TAG_subrange_type)") == 0){ - subrange = 1; - } - - if(subrange && type){ - type->size = size; - - xbt_free(name); - name = NULL; - xbt_free(end); - end = NULL; - xbt_free(type_origin); - type_origin = NULL; - size = 0; - - xbt_free(origin); - origin = NULL; - strtok(xbt_dynar_get_as(split, 0, char *), "<"); - origin = strdup(strtok(NULL, "<")); - xbt_str_rtrim(origin, ">:"); - - }else { - - type = xbt_new0(s_dw_type_t, 1); - type->type = e_dw_array_type; - type->name = xbt_strdup(name); - type->is_pointer_type = is_pointer; - type->id = (void *)strtoul(origin, NULL, 16); - if(type_origin) - type->dw_type_id = xbt_strdup(type_origin); - type->members = NULL; - - xbt_dict_set(*types, origin, type, NULL); - - xbt_free(name); - name = NULL; - xbt_free(end); - end = NULL; - xbt_free(type_origin); - type_origin = NULL; - size = 0; - } - - if(strcmp(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *), "(DW_TAG_subrange_type)") != 0) - break; - - read = xbt_getline(&line, &n, fp); - - } - - xbt_free(origin); - origin = NULL; - - }else{ - - read = xbt_getline(&line, &n, fp); - - } +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 ? +} - } - - xbt_dynar_free(&split); - xbt_dict_free(&variables_origin); - xbt_dict_free(&subprograms_origin); - xbt_free(line); - xbt_free(command); - pclose(fp); - +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); } @@ -1228,10 +587,6 @@ typedef struct s_mc_stack_ignore_variable{ char *frame; }s_mc_stack_ignore_variable_t, *mc_stack_ignore_variable_t; -typedef struct s_mc_data_bss_ignore_variable{ - char *name; -}s_mc_data_bss_ignore_variable_t, *mc_data_bss_ignore_variable_t; - /**************************** Free functions ******************************/ static void stack_ignore_variable_free(mc_stack_ignore_variable_t v){ @@ -1252,15 +607,6 @@ void heap_ignore_region_free_voidp(void *r){ heap_ignore_region_free((mc_heap_ignore_region_t) * (void **) r); } -static void data_bss_ignore_variable_free(mc_data_bss_ignore_variable_t v){ - xbt_free(v->name); - xbt_free(v); -} - -static void data_bss_ignore_variable_free_voidp(void *v){ - data_bss_ignore_variable_free((mc_data_bss_ignore_variable_t) * (void **) v); -} - static void checkpoint_ignore_region_free(mc_checkpoint_ignore_region_t r){ xbt_free(r); } @@ -1375,69 +721,26 @@ void MC_ignore_global_variable(const char *name){ MC_SET_RAW_MEM; - if(mc_global_variables_libsimgrid){ + 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_global_variables_libsimgrid) - 1; + 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_global_variables_libsimgrid, cursor, dw_variable_t); + 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_global_variables_libsimgrid, cursor, NULL); + xbt_dynar_remove_at(mc_libsimgrid_info->global_variables, cursor, NULL); start = 0; - end = xbt_dynar_length(mc_global_variables_libsimgrid) - 1; + 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; } } - - }else{ - - if(mc_data_bss_comparison_ignore == NULL) - mc_data_bss_comparison_ignore = xbt_dynar_new(sizeof(mc_data_bss_ignore_variable_t), data_bss_ignore_variable_free_voidp); - - mc_data_bss_ignore_variable_t var = NULL; - var = xbt_new0(s_mc_data_bss_ignore_variable_t, 1); - var->name = strdup(name); - - if(xbt_dynar_is_empty(mc_data_bss_comparison_ignore)){ - - xbt_dynar_insert_at(mc_data_bss_comparison_ignore, 0, &var); - - }else{ - - unsigned int cursor = 0; - int start = 0; - int end = xbt_dynar_length(mc_data_bss_comparison_ignore) - 1; - mc_data_bss_ignore_variable_t current_var = NULL; - - while(start <= end){ - cursor = (start + end) / 2; - current_var = (mc_data_bss_ignore_variable_t)xbt_dynar_get_as(mc_data_bss_comparison_ignore, cursor, mc_data_bss_ignore_variable_t); - if(strcmp(current_var->name, name) == 0){ - data_bss_ignore_variable_free(var); - if(!raw_mem_set) - MC_UNSET_RAW_MEM; - return; - }else if(strcmp(current_var->name, name) < 0){ - start = cursor + 1; - }else{ - end = cursor - 1; - } - } - - if(strcmp(current_var->name, name) < 0) - xbt_dynar_insert_at(mc_data_bss_comparison_ignore, cursor + 1, &var); - else - xbt_dynar_insert_at(mc_data_bss_comparison_ignore, cursor, &var); - - } - } if(!raw_mem_set) MC_UNSET_RAW_MEM; @@ -1449,7 +752,6 @@ void MC_ignore_local_variable(const char *var_name, const char *frame_name){ MC_SET_RAW_MEM; - if(mc_local_variables_libsimgrid){ unsigned int cursor = 0; dw_variable_t current_var; int start, end; @@ -1457,7 +759,7 @@ void MC_ignore_local_variable(const char *var_name, const char *frame_name){ xbt_dict_cursor_t dict_cursor; char *current_frame_name; dw_frame_t frame; - xbt_dict_foreach(mc_local_variables_libsimgrid, dict_cursor, current_frame_name, 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){ @@ -1474,7 +776,7 @@ void MC_ignore_local_variable(const char *var_name, const char *frame_name){ } } } - xbt_dict_foreach(mc_local_variables_binary, dict_cursor, current_frame_name, frame){ + 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){ @@ -1492,7 +794,8 @@ void MC_ignore_local_variable(const char *var_name, const char *frame_name){ } } }else{ - xbt_dynar_t variables_list = ((dw_frame_t)xbt_dict_get_or_null(mc_local_variables_libsimgrid, frame_name))->variables; + 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){ @@ -1509,61 +812,6 @@ void MC_ignore_local_variable(const char *var_name, const char *frame_name){ } } } - }else{ - - if(mc_stack_comparison_ignore == NULL) - mc_stack_comparison_ignore = xbt_dynar_new(sizeof(mc_stack_ignore_variable_t), stack_ignore_variable_free_voidp); - - mc_stack_ignore_variable_t var = NULL; - var = xbt_new0(s_mc_stack_ignore_variable_t, 1); - var->var_name = strdup(var_name); - var->frame = strdup(frame_name); - - if(xbt_dynar_is_empty(mc_stack_comparison_ignore)){ - - xbt_dynar_insert_at(mc_stack_comparison_ignore, 0, &var); - - }else{ - - unsigned int cursor = 0; - int start = 0; - int end = xbt_dynar_length(mc_stack_comparison_ignore) - 1; - mc_stack_ignore_variable_t current_var = NULL; - - while(start <= end){ - cursor = (start + end) / 2; - current_var = (mc_stack_ignore_variable_t)xbt_dynar_get_as(mc_stack_comparison_ignore, cursor, mc_stack_ignore_variable_t); - if(strcmp(current_var->frame, frame_name) == 0){ - if(strcmp(current_var->var_name, var_name) == 0){ - stack_ignore_variable_free(var); - if(!raw_mem_set) - MC_UNSET_RAW_MEM; - return; - }else if(strcmp(current_var->var_name, var_name) < 0){ - start = cursor + 1; - }else{ - end = cursor - 1; - } - }else if(strcmp(current_var->frame, frame_name) < 0){ - start = cursor + 1; - }else{ - end = cursor - 1; - } - } - - if(strcmp(current_var->frame, frame_name) == 0){ - if(strcmp(current_var->var_name, var_name) < 0){ - xbt_dynar_insert_at(mc_stack_comparison_ignore, cursor + 1, &var); - }else{ - xbt_dynar_insert_at(mc_stack_comparison_ignore, cursor, &var); - } - }else if(strcmp(current_var->frame, frame_name) < 0){ - xbt_dynar_insert_at(mc_stack_comparison_ignore, cursor + 1, &var); - }else{ - xbt_dynar_insert_at(mc_stack_comparison_ignore, cursor, &var); - } - } - } if(!raw_mem_set) MC_UNSET_RAW_MEM; @@ -1655,44 +903,39 @@ void MC_ignore(void *addr, size_t size){ /******************************* Initialisation of MC *******************************/ /*********************************************************************************/ -static void MC_dump_ignored_local_variables(void){ - - if(mc_stack_comparison_ignore == NULL || xbt_dynar_is_empty(mc_stack_comparison_ignore)) - return; - - unsigned int cursor = 0; - mc_stack_ignore_variable_t current_var; - - xbt_dynar_foreach(mc_stack_comparison_ignore, cursor, current_var){ - MC_ignore_local_variable(current_var->var_name, current_var->frame); +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); + } } - - xbt_dynar_free(&mc_stack_comparison_ignore); - mc_stack_comparison_ignore = NULL; - } -static void MC_dump_ignored_global_variables(void){ - - if(mc_data_bss_comparison_ignore == NULL || xbt_dynar_is_empty(mc_data_bss_comparison_ignore)) - return; +static void MC_init_debug_info(void) { + XBT_INFO("Get debug information ..."); - unsigned int cursor = 0; - mc_data_bss_ignore_variable_t current_var; + memory_map_t maps = MC_get_memory_map(); - xbt_dynar_foreach(mc_data_bss_comparison_ignore, cursor, current_var){ - MC_ignore_global_variable(current_var->name); - } + /* 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); - xbt_dynar_free(&mc_data_bss_comparison_ignore); - mc_data_bss_comparison_ignore = NULL; + // 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 @@ -1701,36 +944,7 @@ void MC_init(){ MC_SET_RAW_MEM; MC_init_memory_map_info(); - - mc_local_variables_libsimgrid = xbt_dict_new_homogeneous(NULL); - mc_local_variables_binary = xbt_dict_new_homogeneous(NULL); - mc_global_variables_libsimgrid = xbt_dynar_new(sizeof(dw_variable_t), dw_variable_free_voidp); - mc_global_variables_binary = xbt_dynar_new(sizeof(dw_variable_t), dw_variable_free_voidp); - mc_variables_type_libsimgrid = xbt_dict_new_homogeneous(NULL); - mc_variables_type_binary = xbt_dict_new_homogeneous(NULL); - - XBT_INFO("Get debug information ..."); - - /* Get local variables in binary for state equality detection */ - xbt_dict_t binary_location_list = MC_dwarf_get_location_list(xbt_binary_name); - MC_dwarf_get_variables(xbt_binary_name, binary_location_list, &mc_local_variables_binary, &mc_global_variables_binary, &mc_variables_type_binary); - - /* Get local variables in libsimgrid for state equality detection */ - xbt_dict_t libsimgrid_location_list = MC_dwarf_get_location_list(libsimgrid_path); - MC_dwarf_get_variables(libsimgrid_path, libsimgrid_location_list, &mc_local_variables_libsimgrid, &mc_global_variables_libsimgrid, &mc_variables_type_libsimgrid); - - xbt_dict_free(&libsimgrid_location_list); - xbt_dict_free(&binary_location_list); - - XBT_INFO("Get debug information done !"); - - /* Remove variables ignored before getting list of variables */ - MC_dump_ignored_local_variables(); - MC_dump_ignored_global_variables(); - - /* Get .plt section (start and end addresses) for data libsimgrid and data program comparison */ - MC_get_libsimgrid_plt_section(); - MC_get_binary_plt_section(); + MC_init_debug_info(); /* Init parmap */ parmap = xbt_parmap_mc_new(xbt_os_get_numcores(), XBT_PARMAP_DEFAULT); @@ -1760,6 +974,7 @@ void MC_init(){ 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)); @@ -1865,8 +1080,7 @@ void MC_modelcheck_safety(void) }else{ MC_SET_RAW_MEM; MC_init_memory_map_info(); - MC_get_libsimgrid_plt_section(); - MC_get_binary_plt_section(); + MC_init_debug_info(); MC_UNSET_RAW_MEM; } @@ -1876,6 +1090,9 @@ void MC_modelcheck_safety(void) /* Save the initial state */ initial_state_safety = xbt_new0(s_mc_global_t, 1); initial_state_safety->snapshot = MC_take_snapshot(0); + initial_state_safety->initial_communications_pattern_done = 0; + initial_state_safety->comm_deterministic = 1; + initial_state_safety->send_deterministic = 1; MC_UNSET_RAW_MEM; MC_dpor(); @@ -1930,6 +1147,7 @@ void MC_modelcheck_liveness(){ void MC_exit(void) { xbt_free(mc_time); + MC_memory_exit(); //xbt_abort(); } @@ -1998,6 +1216,7 @@ void MC_replay(xbt_fifo_t stack, int start) xbt_fifo_item_t item, start_item; mc_state_t state; smx_process_t process = NULL; + int comm_pattern = 0; XBT_DEBUG("**** Begin Replay ****"); @@ -2027,6 +1246,8 @@ void MC_replay(xbt_fifo_t stack, int start) xbt_free(key); } } + if(_sg_mc_comms_determinism) + xbt_dynar_reset(communications_pattern); MC_UNSET_RAW_MEM; @@ -2056,8 +1277,25 @@ void MC_replay(xbt_fifo_t stack, int start) xbt_free(req_str); } } - + + if(_sg_mc_comms_determinism){ + if(req->call == SIMCALL_COMM_ISEND) + comm_pattern = 1; + else if(req->call == SIMCALL_COMM_IRECV) + comm_pattern = 2; + } + SIMIX_simcall_pre(req, value); + + if(_sg_mc_comms_determinism){ + MC_SET_RAW_MEM; + if(comm_pattern != 0){ + get_comm_pattern(communications_pattern, req, comm_pattern); + } + MC_UNSET_RAW_MEM; + comm_pattern = 0; + } + MC_wait_for_requests(); count++; @@ -2338,6 +1576,10 @@ void MC_print_statistics(mc_stats_t stats) fprintf(dot_output, "}\n"); fclose(dot_output); } + if(initial_state_safety != NULL && _sg_mc_comms_determinism){ + XBT_INFO("Communication-deterministic : %s", !initial_state_safety->comm_deterministic ? "No" : "Yes"); + XBT_INFO("Send-deterministic : %s", !initial_state_safety->send_deterministic ? "No" : "Yes"); + } MC_UNSET_RAW_MEM; } diff --git a/src/mc/mc_hash.c b/src/mc/mc_hash.c new file mode 100644 index 0000000000..533548bff4 --- /dev/null +++ b/src/mc/mc_hash.c @@ -0,0 +1,303 @@ +/* Copyright (c) 2014. The SimGrid Team. + * All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include +#include + +#include "mc_private.h" +#include "mc/datatypes.h" +#include + +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_hash, mc, + "Logging specific to mc_hash"); + +// This is djb2: +typedef uint64_t mc_hash_t; +#define MC_HASH_INIT ((uint64_t)5381) + +// #define MC_HASH(hash, value) hash = (((hash << 5) + hash) + (uint64_t) value) +#define MC_HASH(hash, value) \ + { hash = (((hash << 5) + hash) + (uint64_t) value);\ + XBT_DEBUG("%s:%i: %"PRIx64" -> %"PRIx64, __FILE__, __LINE__, (uint64_t) value, hash); } + +// ***** Hash state + +typedef struct s_mc_hashing_state { + // Set of pointers/addresses already processed (avoid loops): + mc_address_set_t handled_addresses; +} mc_hashing_state; + +void mc_hash_state_init(mc_hashing_state* state); +void mc_hash_state_destroy(mc_hashing_state* state); + +void mc_hash_state_init(mc_hashing_state* state) { + state->handled_addresses = mc_address_set_new(); +} + +void mc_hash_state_destroy(mc_hashing_state* state) { + mc_address_set_free(&state->handled_addresses); +} + +// TODO, detect and avoid loops + +static bool mc_ignored(const void* address, size_t size) { + mc_heap_ignore_region_t region; + unsigned int cursor = 0; + const void* end = (char*) address + size; + xbt_dynar_foreach(mc_heap_comparison_ignore, cursor, region) { + void* istart = region->address; + void* iend = (char*) region->address + region->size; + + if(address>=istart && address=istart && endtype){ + // Simple case, hash this has binary: + case DW_TAG_base_type: + case DW_TAG_enumeration_type: + { + if(mc_ignored(address, 1)) + return; + mc_hash_binary(hash, address, type->byte_size); + return; + } + + case DW_TAG_array_type: + { + if(mc_ignored(address, type->byte_size)) + return; + + long element_count = type->element_count; + dw_type_t subtype = type->subtype; + if(subtype==NULL) { + XBT_DEBUG("Hash array without subtype"); + return; + } + int i; + for(i=0; i!=element_count; ++i) { + XBT_DEBUG("Hash array element %i", i); + void* subaddress = ((char*)address)+i*subtype->byte_size; + mc_hash_value(hash, state, info, subaddress, subtype); + } + return; + } + + // Get the raw type: + case DW_TAG_typedef: + case DW_TAG_volatile_type: + case DW_TAG_const_type: + case DW_TAG_restrict_type: + { + type = type->subtype; + if(type==NULL) + return; + else + goto top; + } + + case DW_TAG_structure_type: + case DW_TAG_class_type: + { + if(mc_ignored(address, type->byte_size)) + return; + + unsigned int cursor = 0; + dw_type_t member; + xbt_dynar_foreach(type->members, cursor, member){ + XBT_DEBUG("Hash struct member %s", member->name); + if(type->subtype==NULL) + return; + mc_hash_value(hash, state, info, ((char*)address) + member->offset, type->subtype); + } + return; + } + + // Pointer, we hash a single value but it might be an array. + case DW_TAG_pointer_type: + case DW_TAG_reference_type: + case DW_TAG_rvalue_reference_type: + { + if(mc_ignored(address, 1)) + return; + + void* pointed = *(void**)address; + if(pointed==NULL) { + XBT_DEBUG("Hashed pinter is NULL"); + return; + } + + // Avoid loops: + if(mc_address_test(state->handled_addresses, pointed)) { + XBT_DEBUG("Hashed pointed data %p already hashed", pointed); + return; + } + mc_address_add(state->handled_addresses, pointed); + + // Anything outside the R/W segments and the heap is not hashed: + bool valid_pointer = (pointed >= (void*) mc_binary_info->start_rw && pointed <= (void*) mc_binary_info->end_rw) + || (pointed >= (void*) mc_libsimgrid_info->start_rw && pointed <= (void*) mc_libsimgrid_info->end_rw) + || (pointed >= std_heap && pointed < (void*) ((const char*)std_heap + STD_HEAP_SIZE)); + if(!valid_pointer) { + XBT_DEBUG("Hashed pointed data %p is in an ignored range", pointed); + return; + } + + if(type->subtype==NULL) { + XBT_DEBUG("Missing type for %p (type=%s)", pointed, type->dw_type_id); + return; + } + + address = pointed; + type = type->subtype; + goto top; + } + + // Skip this: + case DW_TAG_union_type: + case DW_TAG_subroutine_type: + default: + return; + } +} + + +static void mc_hash_object_globals(mc_hash_t *hash, mc_hashing_state* state, mc_object_info_t info) { + unsigned int cursor = 0; + dw_variable_t variable; + xbt_dynar_foreach(info->global_variables, cursor, variable) { + XBT_DEBUG("Hash global variable %s", variable->name); + + if(variable->type_origin == NULL) { + // Nothing + continue; + } + + dw_type_t type = variable->type; + if(type==NULL) { + // Nothing + continue; + } + + const char* address = variable->address; + bool valid_pointer = (address >= mc_binary_info->start_rw && address <= mc_binary_info->end_rw) + || (address >= mc_libsimgrid_info->start_rw && address <= mc_libsimgrid_info->end_rw) + || (address >= (const char*) std_heap && address < (const char *)std_heap + STD_HEAP_SIZE); + if(!valid_pointer) continue; + + mc_hash_value(hash, state, info, variable->address, type); + } +} + +static void mc_hash_stack_frame( + mc_hash_t *hash, + mc_object_info_t info, unw_cursor_t* unw_cursor, dw_frame_t frame, char* frame_pointer, mc_hashing_state* state + ) { + + // return; // TEMP + + unsigned int cursor = 0; + dw_variable_t variable; + xbt_dynar_foreach(frame->variables, cursor, variable){ + + if(variable->type_origin==NULL) { + XBT_DEBUG("Hash local variable %s without type", variable->name); + continue; + } + if(variable->location == NULL) { + XBT_DEBUG("Hash local variable %s without location", variable->name); + continue; + } + + XBT_DEBUG("Hash local variable %s", variable->name); + + void* variable_address = (void*) MC_dwarf_resolve_location(unw_cursor, variable->location, frame_pointer); + + dw_type_t type = variable->type; + if(type==NULL) { + XBT_DEBUG("Hash local variable %s without loctypeation", variable->name); + continue; + } + + mc_hash_value(hash, state, info, variable_address, type); + } +} + +static void mc_hash_stack(mc_hash_t *hash, mc_snapshot_stack_t stack, mc_hashing_state* state) { + + unsigned cursor = 0; + mc_stack_frame_t stack_frame; + + xbt_dynar_foreach(stack->stack_frames, cursor, stack_frame) { + + MC_HASH(*hash, stack_frame->ip); + + mc_object_info_t info; + if(stack_frame->ip >= (unw_word_t) mc_libsimgrid_info->start_exec && stack_frame->ip < (unw_word_t) mc_libsimgrid_info->end_exec) + info = mc_libsimgrid_info; + else if(stack_frame->ip >= (unw_word_t) mc_binary_info->start_exec && stack_frame->ip < (unw_word_t) mc_binary_info->end_exec) + info = mc_binary_info; + else + continue; + + mc_hash_stack_frame(hash, info, &(stack_frame->unw_cursor), stack_frame->frame, (void*)stack_frame->frame_base, state); + + } +} + +static void mc_hash_stacks(mc_hash_t *hash, mc_hashing_state* state, xbt_dynar_t stacks) { + unsigned int cursor = 0; + mc_snapshot_stack_t current_stack; + + MC_HASH(*hash, xbt_dynar_length(stacks_areas)); + + int i=0; + xbt_dynar_foreach(stacks, cursor, current_stack){ + XBT_DEBUG("Stack %i", i); + mc_hash_stack(hash, current_stack, state); + ++i; + } +} + +uint64_t mc_hash_processes_state(int num_state, xbt_dynar_t stacks) { + XBT_DEBUG("START hash %i", num_state); + + mc_hashing_state state; + mc_hash_state_init(&state); + + mc_hash_t hash = MC_HASH_INIT; + + MC_HASH(hash, xbt_swag_size(simix_global->process_list)); // process count + mc_hash_object_globals(&hash, &state, mc_binary_info); + // mc_hash_object_globals(&hash, &state, mc_libsimgrid_info); + mc_hash_stacks(&hash, &state, stacks); + + mc_hash_state_destroy(&state); + + XBT_DEBUG("END hash %i", num_state); + return hash; +} diff --git a/src/mc/mc_liveness.c b/src/mc/mc_liveness.c index acc580316d..96e6513669 100644 --- a/src/mc/mc_liveness.c +++ b/src/mc/mc_liveness.c @@ -36,6 +36,10 @@ static xbt_dynar_t get_atomic_propositions_values(){ return values; } +/** \brief Find a suitable subrange of candidate duplicates for a given state + * + * See mc_dpor.c with a similar (same?) function. + */ static int get_search_interval(xbt_dynar_t all_pairs, mc_visited_pair_t pair, int *min, int *max){ int raw_mem_set = (mmalloc_get_current_heap() == raw_heap); @@ -114,12 +118,15 @@ static mc_visited_pair_t is_reached_acceptance_pair(int pair_num, xbt_automaton_ index = get_search_interval(acceptance_pairs, pair, &min, &max); if(min != -1 && max != -1){ // Acceptance pair with same number of processes and same heap bytes used exists + + // Parallell implementation /*res = xbt_parmap_mc_apply(parmap, snapshot_compare, xbt_dynar_get_ptr(acceptance_pairs, min), (max-min)+1, pair); if(res != -1){ if(!raw_mem_set) MC_UNSET_RAW_MEM; return ((mc_pair_t)xbt_dynar_get_as(acceptance_pairs, (min+res)-1, mc_pair_t))->num; }*/ + cursor = min; while(cursor <= max){ pair_test = (mc_visited_pair_t)xbt_dynar_get_as(acceptance_pairs, cursor, mc_visited_pair_t); @@ -192,6 +199,9 @@ static void remove_acceptance_pair(int pair_num){ MC_UNSET_RAW_MEM; } +/** \brief Checks whether a given state has already been visited by the algorithm. + * + */ static int is_visited_pair(mc_visited_pair_t pair, int pair_num, xbt_automaton_state_t automaton_state, xbt_dynar_t atomic_propositions){ if(_sg_mc_visited == 0) @@ -264,7 +274,7 @@ static int is_visited_pair(mc_visited_pair_t pair, int pair_num, xbt_automaton_s if(dot_output == NULL) XBT_DEBUG("Pair %d already visited ! (equal to pair %d)", new_pair->num, pair_test->num); else - XBT_DEBUG("Pair %d already visited ! (equal to pair %d (pair %d in dot_output))", new_pair->num, pair_test->num, pair->other_num); + XBT_DEBUG("Pair %d already visited ! (equal to pair %d (pair %d in dot_output))", new_pair->num, pair_test->num, new_pair->other_num); xbt_dynar_remove_at(visited_pairs, cursor, NULL); xbt_dynar_insert_at(visited_pairs, cursor, &new_pair); pair_test->visited_removed = 1; diff --git a/src/mc/mc_memory.c b/src/mc/mc_memory.c index aa38112b9b..cc6350be6f 100644 --- a/src/mc/mc_memory.c +++ b/src/mc/mc_memory.c @@ -39,6 +39,9 @@ void MC_memory_init() #include "xbt_modinter.h" void MC_memory_exit(void) { + MC_free_object_info(&mc_binary_info); + MC_free_object_info(&mc_libsimgrid_info); + if (raw_heap) xbt_mheap_destroy(raw_heap); } diff --git a/src/mc/mc_private.h b/src/mc/mc_private.h index 0f2a556421..97aff1f9cc 100644 --- a/src/mc/mc_private.h +++ b/src/mc/mc_private.h @@ -12,6 +12,8 @@ #ifndef WIN32 #include #endif +#include + #include "mc/mc.h" #include "mc/datatypes.h" #include "xbt/fifo.h" @@ -26,6 +28,9 @@ #include "xbt/strbuff.h" #include "xbt/parmap.h" +typedef struct s_dw_frame s_dw_frame_t, *dw_frame_t; +typedef struct s_mc_function_index_item s_mc_function_index_item_t, *mc_function_index_item_t; + /****************************** Snapshots ***********************************/ #define NB_REGIONS 3 /* binary data (data + BSS) (type = 2), libsimgrid data (data + BSS) (type = 1), std_heap (type = 0)*/ @@ -43,14 +48,28 @@ typedef struct s_mc_snapshot{ size_t *stack_sizes; xbt_dynar_t stacks; xbt_dynar_t to_ignore; - char hash_global[41]; - char hash_local[41]; + uint64_t hash; } s_mc_snapshot_t, *mc_snapshot_t; +/** Information about a given stack frame + * + */ +typedef struct s_mc_stack_frame { + /** Instruction pointer */ + unw_word_t ip; + /** Stack pointer */ + unw_word_t sp; + unw_word_t frame_base; + dw_frame_t frame; + char* frame_name; + unw_cursor_t unw_cursor; +} s_mc_stack_frame_t, *mc_stack_frame_t; + typedef struct s_mc_snapshot_stack{ xbt_dynar_t local_variables; void *stack_pointer; void *real_address; + xbt_dynar_t stack_frames; // mc_stack_frame_t }s_mc_snapshot_stack_t, *mc_snapshot_stack_t; typedef struct s_mc_global_t{ @@ -58,6 +77,9 @@ typedef struct s_mc_global_t{ int raw_mem_set; int prev_pair; char *prev_req; + int initial_communications_pattern_done; + int comm_deterministic; + int send_deterministic; }s_mc_global_t, *mc_global_t; typedef struct s_mc_checkpoint_ignore_region{ @@ -218,25 +240,8 @@ typedef struct s_memory_map { void MC_init_memory_map_info(void); memory_map_t MC_get_memory_map(void); void MC_free_memory_map(memory_map_t map); -void MC_get_libsimgrid_plt_section(void); -void MC_get_binary_plt_section(void); -extern void *start_data_libsimgrid; -extern void *start_data_binary; -extern void *start_bss_binary; extern char *libsimgrid_path; -extern void *start_text_libsimgrid; -extern void *start_text_binary; -extern void *start_bss_libsimgrid; -extern void *start_plt_libsimgrid; -extern void *end_plt_libsimgrid; -extern void *start_plt_binary; -extern void *end_plt_binary; -extern void *start_got_plt_libsimgrid; -extern void *end_got_plt_libsimgrid; -extern void *start_got_plt_binary; -extern void *end_got_plt_binary; - /********************************** Snapshot comparison **********************************/ @@ -248,8 +253,6 @@ typedef struct s_mc_comparison_times{ double libsimgrid_global_variables_comparison_time; double heap_comparison_time; double stacks_comparison_time; - double hash_global_variables_comparison_time; - double hash_local_variables_comparison_time; }s_mc_comparison_times_t, *mc_comparison_times_t; extern __thread mc_comparison_times_t mc_comp_times; @@ -262,7 +265,6 @@ void print_comparison_times(void); //#define MC_DEBUG 1 #define MC_VERBOSE 1 - /********************************** DPOR for safety property **************************************/ typedef enum { @@ -294,8 +296,6 @@ extern xbt_fifo_t mc_stack_liveness; extern mc_global_t initial_state_liveness; extern xbt_automaton_t _mc_property_automaton; extern int compare; -extern xbt_dynar_t mc_stack_comparison_ignore; -extern xbt_dynar_t mc_data_bss_comparison_ignore; typedef struct s_mc_pair{ int num; @@ -333,12 +333,42 @@ void MC_dump_stack_liveness(xbt_fifo_t stack); /********************************** Variables with DWARF **********************************/ -extern xbt_dict_t mc_local_variables_libsimgrid; -extern xbt_dict_t mc_local_variables_binary; -extern xbt_dynar_t mc_global_variables_libsimgrid; -extern xbt_dynar_t mc_global_variables_binary; -extern xbt_dict_t mc_variables_type_libsimgrid; -extern xbt_dict_t mc_variables_type_binary; +#define MC_OBJECT_INFO_EXECUTABLE 1 + +struct s_mc_object_info { + size_t flags; + char* file_name; + char *start_exec, *end_exec; // Executable segment + char *start_rw, *end_rw; // Read-write segment + char *start_ro, *end_ro; // read-only segment + xbt_dict_t local_variables; // xbt_dict_t + xbt_dynar_t global_variables; // xbt_dynar_t + xbt_dict_t types; // xbt_dict_t + xbt_dict_t types_by_name; // xbt_dict_t (full defined type only) + + // Here we sort the minimal information for an efficient (and cache-efficient) + // lookup of a function given an instruction pointer. + // The entries are sorted by low_pc and a binary search can be used to look them up. + xbt_dynar_t functions_index; +}; + +mc_object_info_t MC_new_object_info(void); +mc_object_info_t MC_find_object_info(memory_map_t maps, char* name, int executable); +void MC_free_object_info(mc_object_info_t* p); + +void MC_dwarf_get_variables(mc_object_info_t info); +void MC_dwarf_get_variables_libdw(mc_object_info_t info); +const char* MC_dwarf_attrname(int attr); +const char* MC_dwarf_tagname(int tag); + +dw_frame_t MC_find_function_by_ip(void* ip); +mc_object_info_t MC_ip_find_object_info(void* ip); + +extern mc_object_info_t mc_libsimgrid_info; +extern mc_object_info_t mc_binary_info; + +void MC_find_object_address(memory_map_t maps, mc_object_info_t result); +void MC_post_process_types(mc_object_info_t info); typedef enum { e_dw_loclist, @@ -397,30 +427,53 @@ typedef struct s_dw_location{ }s_dw_location_t, *dw_location_t; typedef struct s_dw_location_entry{ - unsigned long lowpc; - unsigned long highpc; + void* lowpc; + void* highpc; dw_location_t location; }s_dw_location_entry_t, *dw_location_entry_t; typedef struct s_dw_variable{ + Dwarf_Off dwarf_offset; /* Global offset of the field. */ int global; char *name; char *type_origin; - union{ - dw_location_t location; - void *address; - }address; + dw_type_t type; + + // Use either of: + dw_location_t location; + void* address; + }s_dw_variable_t, *dw_variable_t; -typedef struct s_dw_frame{ +struct s_dw_frame{ char *name; void *low_pc; void *high_pc; dw_location_t frame_base; - xbt_dynar_t variables; /* Cannot use dict, there may be several variables with the same name (in different lexical blocks)*/ - unsigned long int start; - unsigned long int end; -}s_dw_frame_t, *dw_frame_t; + xbt_dynar_t /* */ variables; /* Cannot use dict, there may be several variables with the same name (in different lexical blocks)*/ + unsigned long int start; /* DWARF offset of the subprogram */ + unsigned long int end; /* Dwarf offset of the next sibling */ +}; + +struct s_mc_function_index_item { + void* low_pc, *high_pc; + dw_frame_t function; +}; + +void dw_type_free(dw_type_t t); +void dw_variable_free(dw_variable_t v); +void dw_variable_free_voidp(void *t); + +void MC_dwarf_register_global_variable(mc_object_info_t info, dw_variable_t variable); +void MC_register_variable(mc_object_info_t info, dw_frame_t frame, dw_variable_t variable); +void MC_dwarf_register_non_global_variable(mc_object_info_t info, dw_frame_t frame, dw_variable_t variable); +void MC_dwarf_register_variable(mc_object_info_t info, dw_frame_t frame, dw_variable_t variable); +void* MC_object_base_address(mc_object_info_t info); + +/********************************** DWARF **********************************/ + +Dwarf_Off MC_dwarf_resolve_location(unw_cursor_t* c, dw_location_t location, void* frame_pointer_address); +void* mc_find_frame_base(void* ip, dw_frame_t frame, unw_cursor_t* unw_cursor); /********************************** Miscellaneous **********************************/ @@ -428,10 +481,47 @@ typedef struct s_local_variable{ char *frame; unsigned long ip; char *name; - char *type; + dw_type_t type; void *address; int region; }s_local_variable_t, *local_variable_t; +/********************************* Communications pattern ***************************/ + +typedef struct s_mc_comm_pattern{ + int num; + smx_action_t comm; + e_smx_comm_type_t type; + int completed; + unsigned long src_proc; + unsigned long dst_proc; + char *rdv; + size_t data_size; + void *data; + int matched_comm; +}s_mc_comm_pattern_t, *mc_comm_pattern_t; + +extern xbt_dynar_t communications_pattern; + +void get_comm_pattern(xbt_dynar_t communications_pattern, smx_simcall_t request, int call); + +/* *********** Sets *********** */ + +typedef struct s_mc_address_set *mc_address_set_t; + +mc_address_set_t mc_address_set_new(); +mc_address_set_t mc_address_set_free(mc_address_set_t* p); +void mc_address_add(mc_address_set_t p, const void* value); +bool mc_address_test(mc_address_set_t p, const void* value); + +/* *********** Hash *********** */ + +/** \brief Hash the current state + * \param num_state number of states + * \param stacks stacks (mc_snapshot_stak_t) used fot the stack unwinding informations + * \result resulting hash + * */ +uint64_t mc_hash_processes_state(int num_state, xbt_dynar_t stacks); + #endif diff --git a/src/mc/mc_request.c b/src/mc/mc_request.c index 1392a35868..6ffee19348 100644 --- a/src/mc/mc_request.c +++ b/src/mc/mc_request.c @@ -17,7 +17,11 @@ int MC_request_depend(smx_simcall_t r1, smx_simcall_t r2) { return TRUE; if (r1->issuer == r2->issuer) - return FALSE; + return FALSE; + + /* Wait with timeout transitions are not considered by the independance theorem, thus we consider them as dependant with all other transitions */ + if((r1->call == SIMCALL_COMM_WAIT && simcall_comm_wait__get__timeout(r1) > 0) || (r2->call == SIMCALL_COMM_WAIT && simcall_comm_wait__get__timeout(r2) > 0)) + return TRUE; if(r1->call == SIMCALL_COMM_ISEND && r2->call == SIMCALL_COMM_IRECV) return FALSE; @@ -335,6 +339,8 @@ int MC_request_is_enabled(smx_simcall_t req) } }else{ act = simcall_comm_wait__get__comm(req); + if(act->comm.detached && act->comm.src_proc == NULL && act->comm.type == SIMIX_COMM_READY) + return (act->comm.dst_proc != NULL); return (act->comm.src_proc && act->comm.dst_proc); } break; diff --git a/src/mc/mc_set.cpp b/src/mc/mc_set.cpp new file mode 100644 index 0000000000..b04c1ff54b --- /dev/null +++ b/src/mc/mc_set.cpp @@ -0,0 +1,36 @@ +/* Copyright (c) 2007-2013. The SimGrid Team. + * All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include +#include + +typedef std::set* mc_address_set_t; + +extern "C" { + +mc_address_set_t mc_address_set_new(); +mc_address_set_t mc_address_set_free(mc_address_set_t* p); +void mc_address_add(mc_address_set_t p, const void* value); +bool mc_address_test(mc_address_set_t p, const void* value); + +mc_address_set_t mc_address_set_new() { + return new std::set(); +} + +mc_address_set_t mc_address_set_free(mc_address_set_t* p) { + delete *p; + *p = NULL; +} + +void mc_address_add(mc_address_set_t p, const void* value) { + p->insert(value); +} + +bool mc_address_test(mc_address_set_t p, const void* value) { + return p->find(value) != p->end(); +} + +}; diff --git a/src/mc/mc_state.c b/src/mc/mc_state.c index d0cef470a0..64dcb1a3b6 100644 --- a/src/mc/mc_state.c +++ b/src/mc/mc_state.c @@ -143,6 +143,7 @@ smx_simcall_t MC_state_get_request(mc_state_t state, int *value) smx_process_t process = NULL; mc_procstate_t procstate = NULL; unsigned int start_count; + smx_action_t act = NULL; xbt_swag_foreach(process, simix_global->process_list){ procstate = &state->proc_status[process->pid]; @@ -186,11 +187,14 @@ smx_simcall_t MC_state_get_request(mc_state_t state, int *value) break; case SIMCALL_COMM_WAIT: - if(simcall_comm_wait__get__comm(&process->simcall)->comm.src_proc - && simcall_comm_wait__get__comm(&process->simcall)->comm.dst_proc){ + act = simcall_comm_wait__get__comm(&process->simcall); + if(act->comm.src_proc && act->comm.dst_proc){ *value = 0; }else{ - *value = -1; + if(act->comm.src_proc == NULL && act->comm.type == SIMIX_COMM_READY && act->comm.detached == 1) + *value = 0; + else + *value = -1; } procstate->state = MC_DONE; return &process->simcall; diff --git a/src/simgrid/sg_config.c b/src/simgrid/sg_config.c index 2b4840f9b2..743b4527c0 100644 --- a/src/simgrid/sg_config.c +++ b/src/simgrid/sg_config.c @@ -580,7 +580,7 @@ void sg_config_init(int *argc, char **argv) /* do stateful model-checking */ xbt_cfg_register(&_sg_cfg_set, "model-check/checkpoint", "Specify the amount of steps between checkpoints during stateful model-checking (default: 0 => stateless verification). " - "If value=on, one checkpoint is saved for each step => faster verification, but huge memory consumption; higher values are good compromises between speed and memory consumption.", + "If value=1, one checkpoint is saved for each step => faster verification, but huge memory consumption; higher values are good compromises between speed and memory consumption.", xbt_cfgelm_int, 0, 1, _mc_cfg_cb_checkpoint, NULL); xbt_cfg_setdefault_int(_sg_cfg_set, "model-check/checkpoint", 0); @@ -590,6 +590,12 @@ void sg_config_init(int *argc, char **argv) xbt_cfgelm_string, 0, 1, _mc_cfg_cb_property, NULL); xbt_cfg_setdefault_string(_sg_cfg_set, "model-check/property", ""); + /* do determinism model-checking */ + xbt_cfg_register(&_sg_cfg_set, "model-check/communications_determinism", + "Enable/disable the detection of determinism in the communications schemes", + xbt_cfgelm_boolean, 0, 1, _mc_cfg_cb_comms_determinism, NULL); + xbt_cfg_setdefault_boolean(_sg_cfg_set, "model-check/communications_determinism", "no"); + /* Specify the kind of model-checking reduction */ xbt_cfg_register(&_sg_cfg_set, "model-check/reduction", "Specify the kind of exploration reduction (either none or DPOR)", @@ -602,6 +608,12 @@ void sg_config_init(int *argc, char **argv) xbt_cfgelm_boolean, 0, 1, _mc_cfg_cb_timeout, NULL); xbt_cfg_setdefault_boolean(_sg_cfg_set, "model-check/timeout", "no"); + /* Enable/disable global hash computation with model-checking */ + xbt_cfg_register(&_sg_cfg_set, "model-check/hash", + "Enable/Disable state hash for state comparison", + xbt_cfgelm_boolean, 0, 1, _mc_cfg_cb_hash, NULL); + xbt_cfg_setdefault_boolean(_sg_cfg_set, "model-check/hash", "no"); + /* Set max depth exploration */ xbt_cfg_register(&_sg_cfg_set, "model-check/max_depth", "Specify the max depth of exploration (default : 1000)", diff --git a/src/simix/smx_network.c b/src/simix/smx_network.c index 9797825fc9..09ab3cf3de 100644 --- a/src/simix/smx_network.c +++ b/src/simix/smx_network.c @@ -31,8 +31,6 @@ static void SIMIX_comm_start(smx_action_t action); void SIMIX_network_init(void) { rdv_points = xbt_dict_new_homogeneous(SIMIX_rdv_free); - if(MC_is_active()) - MC_ignore_global_variable("smx_total_comms"); } void SIMIX_network_exit(void) diff --git a/src/xbt/backtrace_linux.c b/src/xbt/backtrace_linux.c index 37310485c7..b32ec96cb0 100644 --- a/src/xbt/backtrace_linux.c +++ b/src/xbt/backtrace_linux.c @@ -13,6 +13,7 @@ #include "xbt/module.h" /* xbt_binary_name */ #include "xbt_modinter.h" /* backtrace initialization headers */ #ifdef HAVE_MC +#define UNW_LOCAL_ONLY #include #endif /* end of "useless" inclusions */ diff --git a/src/xbt/mmalloc/mm_diff.c b/src/xbt/mmalloc/mm_diff.c index 276218593d..bd2923c77c 100644 --- a/src/xbt/mmalloc/mm_diff.c +++ b/src/xbt/mmalloc/mm_diff.c @@ -11,6 +11,7 @@ #include "mc/mc.h" #include "xbt/mmalloc.h" #include "mc/datatypes.h" +#include "mc/mc_private.h" XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mm_diff, xbt, "Logging specific to mm_diff in mmalloc"); @@ -132,12 +133,16 @@ static int compare_backtrace(int b1, int f1, int b2, int f2){ typedef char* type_name; -__thread void *s_heap = NULL, *heapbase1 = NULL, *heapbase2 = NULL; -__thread malloc_info *heapinfo1 = NULL, *heapinfo2 = NULL; -__thread size_t heaplimit = 0, heapsize1 = 0, heapsize2 = 0; -__thread xbt_dynar_t to_ignore1 = NULL, to_ignore2 = NULL; -__thread heap_area_t **equals_to1, **equals_to2; -__thread type_name **types1, **types2; +struct s_mm_diff { + void *s_heap, *heapbase1, *heapbase2; + malloc_info *heapinfo1, *heapinfo2; + size_t heaplimit, heapsize1, heapsize2; + xbt_dynar_t to_ignore1, to_ignore2; + heap_area_t **equals_to1, **equals_to2; + type_name **types1, **types2; +}; + +__thread struct s_mm_diff* mm_diff_info = NULL; /*********************************** Free functions ************************************/ @@ -242,7 +247,7 @@ static int is_block_stack(int block){ return 0; } -static void match_equals(xbt_dynar_t list){ +static void match_equals(struct s_mm_diff *state, xbt_dynar_t list){ unsigned int cursor = 0; heap_area_pair_t current_pair; @@ -252,121 +257,116 @@ static void match_equals(xbt_dynar_t list){ if(current_pair->fragment1 != -1){ - if(equals_to1[current_pair->block1][current_pair->fragment1] != NULL){ - previous_area = equals_to1[current_pair->block1][current_pair->fragment1]; - heap_area_free(equals_to2[previous_area->block][previous_area->fragment]); - equals_to2[previous_area->block][previous_area->fragment] = NULL; + if(state->equals_to1[current_pair->block1][current_pair->fragment1] != NULL){ + previous_area = state->equals_to1[current_pair->block1][current_pair->fragment1]; + heap_area_free(state->equals_to2[previous_area->block][previous_area->fragment]); + state->equals_to2[previous_area->block][previous_area->fragment] = NULL; heap_area_free(previous_area); } - if(equals_to2[current_pair->block2][current_pair->fragment2] != NULL){ - previous_area = equals_to2[current_pair->block2][current_pair->fragment2]; - heap_area_free(equals_to1[previous_area->block][previous_area->fragment]); - equals_to1[previous_area->block][previous_area->fragment] = NULL; + if(state->equals_to2[current_pair->block2][current_pair->fragment2] != NULL){ + previous_area = state->equals_to2[current_pair->block2][current_pair->fragment2]; + heap_area_free(state->equals_to1[previous_area->block][previous_area->fragment]); + state->equals_to1[previous_area->block][previous_area->fragment] = NULL; heap_area_free(previous_area); } - equals_to1[current_pair->block1][current_pair->fragment1] = new_heap_area(current_pair->block2, current_pair->fragment2); - equals_to2[current_pair->block2][current_pair->fragment2] = new_heap_area(current_pair->block1, current_pair->fragment1); + state->equals_to1[current_pair->block1][current_pair->fragment1] = new_heap_area(current_pair->block2, current_pair->fragment2); + state->equals_to2[current_pair->block2][current_pair->fragment2] = new_heap_area(current_pair->block1, current_pair->fragment1); }else{ - if(equals_to1[current_pair->block1][0] != NULL){ - previous_area = equals_to1[current_pair->block1][0]; - heap_area_free(equals_to2[previous_area->block][0]); - equals_to2[previous_area->block][0] = NULL; + if(state->equals_to1[current_pair->block1][0] != NULL){ + previous_area = state->equals_to1[current_pair->block1][0]; + heap_area_free(state->equals_to2[previous_area->block][0]); + state->equals_to2[previous_area->block][0] = NULL; heap_area_free(previous_area); } - if(equals_to2[current_pair->block2][0] != NULL){ - previous_area = equals_to2[current_pair->block2][0]; - heap_area_free(equals_to1[previous_area->block][0]); - equals_to1[previous_area->block][0] = NULL; + if(state->equals_to2[current_pair->block2][0] != NULL){ + previous_area = state->equals_to2[current_pair->block2][0]; + heap_area_free(state->equals_to1[previous_area->block][0]); + state->equals_to1[previous_area->block][0] = NULL; heap_area_free(previous_area); } - equals_to1[current_pair->block1][0] = new_heap_area(current_pair->block2, current_pair->fragment2); - equals_to2[current_pair->block2][0] = new_heap_area(current_pair->block1, current_pair->fragment1); + state->equals_to1[current_pair->block1][0] = new_heap_area(current_pair->block2, current_pair->fragment2); + state->equals_to2[current_pair->block2][0] = new_heap_area(current_pair->block1, current_pair->fragment1); } } } -static int equal_blocks(int b1, int b2){ +static int equal_blocks(struct s_mm_diff *state, int b1, int b2){ - if(equals_to1[b1][0]->block == b2 && equals_to2[b2][0]->block == b1) + if(state->equals_to1[b1][0]->block == b2 && state->equals_to2[b2][0]->block == b1) return 1; return 0; } -static int equal_fragments(int b1, int f1, int b2, int f2){ +static int equal_fragments(struct s_mm_diff *state, int b1, int f1, int b2, int f2){ - if(equals_to1[b1][f1]->block == b2 && equals_to1[b1][f1]->fragment == f2 && equals_to2[b2][f2]->block == b1 && equals_to2[b2][f2]->fragment == f1) + if(state->equals_to1[b1][f1]->block == b2 + && state->equals_to1[b1][f1]->fragment == f2 + && state->equals_to2[b2][f2]->block == b1 + && state->equals_to2[b2][f2]->fragment == f1) return 1; return 0; } int init_heap_information(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dynar_t i1, xbt_dynar_t i2){ + if(mm_diff_info==NULL) { + mm_diff_info = xbt_new0(struct s_mm_diff, 1); + } + struct s_mm_diff *state = mm_diff_info; - if((((struct mdesc *)heap1)->heaplimit != ((struct mdesc *)heap2)->heaplimit) || ((((struct mdesc *)heap1)->heapsize != ((struct mdesc *)heap2)->heapsize) )) + if((((struct mdesc *)heap1)->heaplimit != ((struct mdesc *)heap2)->heaplimit) + || ((((struct mdesc *)heap1)->heapsize != ((struct mdesc *)heap2)->heapsize) )) return -1; int i, j; - heaplimit = ((struct mdesc *)heap1)->heaplimit; + state->heaplimit = ((struct mdesc *)heap1)->heaplimit; - s_heap = (char *)mmalloc_get_current_heap() - STD_HEAP_SIZE - getpagesize(); + state->s_heap = (char *)mmalloc_get_current_heap() - STD_HEAP_SIZE - getpagesize(); - heapbase1 = (char *)heap1 + BLOCKSIZE; - heapbase2 = (char *)heap2 + BLOCKSIZE; + state->heapbase1 = (char *)heap1 + BLOCKSIZE; + state->heapbase2 = (char *)heap2 + BLOCKSIZE; - heapinfo1 = (malloc_info *)((char *)heap1 + ((uintptr_t)((char *)((struct mdesc *)heap1)->heapinfo - (char *)s_heap))); - heapinfo2 = (malloc_info *)((char *)heap2 + ((uintptr_t)((char *)((struct mdesc *)heap2)->heapinfo - (char *)s_heap))); + state->heapinfo1 = (malloc_info *)((char *)heap1 + ((uintptr_t)((char *)((struct mdesc *)heap1)->heapinfo - (char *)state->s_heap))); + state->heapinfo2 = (malloc_info *)((char *)heap2 + ((uintptr_t)((char *)((struct mdesc *)heap2)->heapinfo - (char *)state->s_heap))); - heapsize1 = heap1->heapsize; - heapsize2 = heap2->heapsize; + state->heapsize1 = heap1->heapsize; + state->heapsize2 = heap2->heapsize; - to_ignore1 = i1; - to_ignore2 = i2; + state->to_ignore1 = i1; + state-> to_ignore2 = i2; - equals_to1 = malloc(heaplimit * sizeof(heap_area_t *)); - types1 = malloc(heaplimit * sizeof(type_name *)); - for(i=0; i<=heaplimit; i++){ - equals_to1[i] = malloc(MAX_FRAGMENT_PER_BLOCK * sizeof(heap_area_t)); - types1[i] = malloc(MAX_FRAGMENT_PER_BLOCK * sizeof(type_name)); + state->equals_to1 = malloc(state->heaplimit * sizeof(heap_area_t *)); + state->types1 = malloc(state->heaplimit * sizeof(type_name *)); + for(i=0; i<=state->heaplimit; i++){ + state->equals_to1[i] = malloc(MAX_FRAGMENT_PER_BLOCK * sizeof(heap_area_t)); + state->types1[i] = malloc(MAX_FRAGMENT_PER_BLOCK * sizeof(type_name)); for(j=0; jequals_to1[i][j] = NULL; + state->types1[i][j] = NULL; } } - equals_to2 = malloc(heaplimit * sizeof(heap_area_t *)); - types2 = malloc(heaplimit * sizeof(type_name *)); - for(i=0; i<=heaplimit; i++){ - equals_to2[i] = malloc(MAX_FRAGMENT_PER_BLOCK * sizeof(heap_area_t)); - types2[i] = malloc(MAX_FRAGMENT_PER_BLOCK * sizeof(type_name)); + state->equals_to2 = malloc(state->heaplimit * sizeof(heap_area_t *)); + state->types2 = malloc(state->heaplimit * sizeof(type_name *)); + for(i=0; i<=state->heaplimit; i++){ + state->equals_to2[i] = malloc(MAX_FRAGMENT_PER_BLOCK * sizeof(heap_area_t)); + state->types2[i] = malloc(MAX_FRAGMENT_PER_BLOCK * sizeof(type_name)); for(j=0; jequals_to2[i][j] = NULL; + state->types2[i][j] = NULL; } } if(MC_is_active()){ - MC_ignore_global_variable("heaplimit"); - MC_ignore_global_variable("s_heap"); - MC_ignore_global_variable("heapbase1"); - MC_ignore_global_variable("heapbase2"); - MC_ignore_global_variable("heapinfo1"); - MC_ignore_global_variable("heapinfo2"); - MC_ignore_global_variable("heapsize1"); - MC_ignore_global_variable("heapsize2"); - MC_ignore_global_variable("to_ignore1"); - MC_ignore_global_variable("to_ignore2"); - MC_ignore_global_variable("equals_to1"); - MC_ignore_global_variable("equals_to2"); - MC_ignore_global_variable("types1"); - MC_ignore_global_variable("types2"); + MC_ignore_global_variable("mm_diff_info"); } return 0; @@ -375,40 +375,44 @@ int init_heap_information(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dynar_t i1, void reset_heap_information(){ + struct s_mm_diff *state = mm_diff_info; + size_t i = 0, j; - for(i=0; i<=heaplimit; i++){ + for(i=0; i<=state->heaplimit; i++){ for(j=0; jequals_to1[i][j]); + state->equals_to1[i][j] = NULL; + heap_area_free(state->equals_to2[i][j]); + state-> equals_to2[i][j] = NULL; + xbt_free(state->types1[i][j]); + state->types1[i][j] = NULL; + xbt_free(state->types2[i][j]); + state->types2[i][j] = NULL; } - free(equals_to1[i]); - free(equals_to2[i]); - free(types1[i]); - free(types2[i]); + free(state->equals_to1[i]); + free(state->equals_to2[i]); + free(state->types1[i]); + free(state->types2[i]); } - free(equals_to1); - free(equals_to2); - free(types1); - free(types2); + free(state->equals_to1); + free(state->equals_to2); + free(state->types1); + free(state->types2); - s_heap = NULL, heapbase1 = NULL, heapbase2 = NULL; - heapinfo1 = NULL, heapinfo2 = NULL; - heaplimit = 0, heapsize1 = 0, heapsize2 = 0; - to_ignore1 = NULL, to_ignore2 = NULL; - equals_to1 = NULL, equals_to2 = NULL; - types1 = NULL, types2 = NULL; + state->s_heap = NULL, state->heapbase1 = NULL, state->heapbase2 = NULL; + state->heapinfo1 = NULL, state->heapinfo2 = NULL; + state->heaplimit = 0, state->heapsize1 = 0, state->heapsize2 = 0; + state->to_ignore1 = NULL, state->to_ignore2 = NULL; + state->equals_to1 = NULL, state->equals_to2 = NULL; + state->types1 = NULL, state->types2 = NULL; } -int mmalloc_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dict_t all_types, xbt_dict_t other_types){ +int mmalloc_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2, mc_object_info_t info, mc_object_info_t other_info){ + + struct s_mm_diff *state = mm_diff_info; if(heap1 == NULL && heap2 == NULL){ XBT_DEBUG("Malloc descriptors null"); @@ -428,27 +432,27 @@ int mmalloc_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dict_t all_ty i1 = 1; - while(i1 <= heaplimit){ + while(i1 <= state->heaplimit){ - if(heapinfo1[i1].type == -1){ /* Free block */ + if(state->heapinfo1[i1].type == -1){ /* Free block */ i1++; continue; } - addr_block1 = ((void*) (((ADDR2UINT(i1)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)s_heap)->heapbase)); + addr_block1 = ((void*) (((ADDR2UINT(i1)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)state->s_heap)->heapbase)); - if(heapinfo1[i1].type == 0){ /* Large block */ + if(state->heapinfo1[i1].type == 0){ /* Large block */ if(is_stack(addr_block1)){ - for(k=0; k < heapinfo1[i1].busy_block.size; k++) - equals_to1[i1+k][0] = new_heap_area(i1, -1); - for(k=0; k < heapinfo2[i1].busy_block.size; k++) - equals_to2[i1+k][0] = new_heap_area(i1, -1); - i1 += heapinfo1[i1].busy_block.size; + for(k=0; k < state->heapinfo1[i1].busy_block.size; k++) + state->equals_to1[i1+k][0] = new_heap_area(i1, -1); + for(k=0; k < state->heapinfo2[i1].busy_block.size; k++) + state->equals_to2[i1+k][0] = new_heap_area(i1, -1); + i1 += state->heapinfo1[i1].busy_block.size; continue; } - if(equals_to1[i1][0] != NULL){ + if(state->equals_to1[i1][0] != NULL){ i1++; continue; } @@ -458,21 +462,21 @@ int mmalloc_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dict_t all_ty res_compare = 0; /* Try first to associate to same block in the other heap */ - if(heapinfo2[i1].type == heapinfo1[i1].type){ + if(state->heapinfo2[i1].type == state->heapinfo1[i1].type){ - if(equals_to2[i1][0] == NULL){ + if(state->equals_to2[i1][0] == NULL){ - addr_block2 = ((void*) (((ADDR2UINT(i1)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)s_heap)->heapbase)); + addr_block2 = ((void*) (((ADDR2UINT(i1)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)state->s_heap)->heapbase)); - res_compare = compare_heap_area(addr_block1, addr_block2, NULL, all_types, other_types, NULL, 0); + res_compare = compare_heap_area(addr_block1, addr_block2, NULL, info, other_info, NULL, 0); if(res_compare != 1){ - for(k=1; k < heapinfo2[i1].busy_block.size; k++) - equals_to2[i1+k][0] = new_heap_area(i1, -1); - for(k=1; k < heapinfo1[i1].busy_block.size; k++) - equals_to1[i1+k][0] = new_heap_area(i1, -1); + for(k=1; k < state->heapinfo2[i1].busy_block.size; k++) + state->equals_to2[i1+k][0] = new_heap_area(i1, -1); + for(k=1; k < state->heapinfo1[i1].busy_block.size; k++) + state->equals_to1[i1+k][0] = new_heap_area(i1, -1); equal = 1; - i1 += heapinfo1[i1].busy_block.size; + i1 += state->heapinfo1[i1].busy_block.size; } xbt_dynar_reset(previous); @@ -481,34 +485,34 @@ int mmalloc_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dict_t all_ty } - while(i2 <= heaplimit && !equal){ + while(i2 <= state->heaplimit && !equal){ - addr_block2 = ((void*) (((ADDR2UINT(i2)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)s_heap)->heapbase)); + addr_block2 = ((void*) (((ADDR2UINT(i2)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)state->s_heap)->heapbase)); if(i2 == i1){ i2++; continue; } - if(heapinfo2[i2].type != 0){ + if(state->heapinfo2[i2].type != 0){ i2++; continue; } - if(equals_to2[i2][0] != NULL){ + if(state->equals_to2[i2][0] != NULL){ i2++; continue; } - res_compare = compare_heap_area(addr_block1, addr_block2, NULL, all_types, other_types, NULL, 0); + res_compare = compare_heap_area(addr_block1, addr_block2, NULL, info, other_info, NULL, 0); if(res_compare != 1 ){ - for(k=1; k < heapinfo2[i2].busy_block.size; k++) - equals_to2[i2+k][0] = new_heap_area(i1, -1); - for(k=1; k < heapinfo1[i1].busy_block.size; k++) - equals_to1[i1+k][0] = new_heap_area(i2, -1); + for(k=1; k < state->heapinfo2[i2].busy_block.size; k++) + state->equals_to2[i2+k][0] = new_heap_area(i1, -1); + for(k=1; k < state->heapinfo1[i1].busy_block.size; k++) + state->equals_to1[i1+k][0] = new_heap_area(i2, -1); equal = 1; - i1 += heapinfo1[i1].busy_block.size; + i1 += state->heapinfo1[i1].busy_block.size; } xbt_dynar_reset(previous); @@ -518,36 +522,36 @@ int mmalloc_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dict_t all_ty } if(!equal){ - XBT_DEBUG("Block %zu not found (size_used = %zu, addr = %p)", i1, heapinfo1[i1].busy_block.busy_size, addr_block1); - i1 = heaplimit + 1; + XBT_DEBUG("Block %zu not found (size_used = %zu, addr = %p)", i1, state->heapinfo1[i1].busy_block.busy_size, addr_block1); + i1 = state->heaplimit + 1; nb_diff1++; //i1++; } }else{ /* Fragmented block */ - for(j1=0; j1 < (size_t) (BLOCKSIZE >> heapinfo1[i1].type); j1++){ + for(j1=0; j1 < (size_t) (BLOCKSIZE >> state->heapinfo1[i1].type); j1++){ - if(heapinfo1[i1].busy_frag.frag_size[j1] == -1) /* Free fragment */ + if(state->heapinfo1[i1].busy_frag.frag_size[j1] == -1) /* Free fragment */ continue; - if(equals_to1[i1][j1] != NULL) + if(state->equals_to1[i1][j1] != NULL) continue; - addr_frag1 = (void*) ((char *)addr_block1 + (j1 << heapinfo1[i1].type)); + addr_frag1 = (void*) ((char *)addr_block1 + (j1 << state->heapinfo1[i1].type)); i2 = 1; equal = 0; /* Try first to associate to same fragment in the other heap */ - if(heapinfo2[i1].type == heapinfo1[i1].type){ + if(state->heapinfo2[i1].type == state->heapinfo1[i1].type){ - if(equals_to2[i1][j1] == NULL){ + if(state->equals_to2[i1][j1] == NULL){ - addr_block2 = ((void*) (((ADDR2UINT(i1)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)s_heap)->heapbase)); - addr_frag2 = (void*) ((char *)addr_block2 + (j1 << ((xbt_mheap_t)s_heap)->heapinfo[i1].type)); + addr_block2 = ((void*) (((ADDR2UINT(i1)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)state->s_heap)->heapbase)); + addr_frag2 = (void*) ((char *)addr_block2 + (j1 << ((xbt_mheap_t)state->s_heap)->heapinfo[i1].type)); - res_compare = compare_heap_area(addr_frag1, addr_frag2, NULL, all_types, other_types, NULL, 0); + res_compare = compare_heap_area(addr_frag1, addr_frag2, NULL, info, other_info, NULL, 0); if(res_compare != 1) equal = 1; @@ -558,25 +562,25 @@ int mmalloc_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dict_t all_ty } - while(i2 <= heaplimit && !equal){ + while(i2 <= state->heaplimit && !equal){ - if(heapinfo2[i2].type <= 0){ + if(state->heapinfo2[i2].type <= 0){ i2++; continue; } - for(j2=0; j2 < (size_t) (BLOCKSIZE >> heapinfo2[i2].type); j2++){ + for(j2=0; j2 < (size_t) (BLOCKSIZE >> state->heapinfo2[i2].type); j2++){ if(i2 == i1 && j2 == j1) continue; - if(equals_to2[i2][j2] != NULL) + if(state->equals_to2[i2][j2] != NULL) continue; - addr_block2 = ((void*) (((ADDR2UINT(i2)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)s_heap)->heapbase)); - addr_frag2 = (void*) ((char *)addr_block2 + (j2 <<((xbt_mheap_t)s_heap)->heapinfo[i2].type)); + addr_block2 = ((void*) (((ADDR2UINT(i2)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)state->s_heap)->heapbase)); + addr_frag2 = (void*) ((char *)addr_block2 + (j2 <<((xbt_mheap_t)state->s_heap)->heapinfo[i2].type)); - res_compare = compare_heap_area(addr_frag1, addr_frag2, NULL, all_types, other_types, NULL, 0); + res_compare = compare_heap_area(addr_frag1, addr_frag2, NULL, info, other_info, NULL, 0); if(res_compare != 1){ equal = 1; @@ -593,9 +597,9 @@ int mmalloc_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dict_t all_ty } if(!equal){ - XBT_DEBUG("Block %zu, fragment %zu not found (size_used = %zd, address = %p)\n", i1, j1, heapinfo1[i1].busy_frag.frag_size[j1], addr_frag1); - i2 = heaplimit + 1; - i1 = heaplimit + 1; + XBT_DEBUG("Block %zu, fragment %zu not found (size_used = %zd, address = %p)\n", i1, j1, state->heapinfo1[i1].busy_frag.frag_size[j1], addr_frag1); + i2 = state->heaplimit + 1; + i1 = state->heaplimit + 1; nb_diff1++; break; } @@ -612,14 +616,14 @@ int mmalloc_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dict_t all_ty size_t i = 1, j = 0; void *real_addr_frag1 = NULL, *real_addr_block1 = NULL, *real_addr_block2 = NULL, *real_addr_frag2 = NULL; - while(i<=heaplimit){ - if(heapinfo1[i].type == 0){ - if(i1 == heaplimit){ - if(heapinfo1[i].busy_block.busy_size > 0){ - if(equals_to1[i][0] == NULL){ + while(i<=state->heaplimit){ + if(state->heapinfo1[i].type == 0){ + if(i1 == state->heaplimit){ + if(state->heapinfo1[i].busy_block.busy_size > 0){ + if(state->equals_to1[i][0] == NULL){ if(XBT_LOG_ISENABLED(mm_diff, xbt_log_priority_debug)){ - addr_block1 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase1)); - XBT_DEBUG("Block %zu (%p) not found (size used = %zu)", i, addr_block1, heapinfo1[i].busy_block.busy_size); + addr_block1 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)state->heapbase1)); + XBT_DEBUG("Block %zu (%p) not found (size used = %zu)", i, addr_block1, state->heapinfo1[i].busy_block.busy_size); //mmalloc_backtrace_block_display((void*)heapinfo1, i); } nb_diff1++; @@ -627,17 +631,17 @@ int mmalloc_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dict_t all_ty } } } - if(heapinfo1[i].type > 0){ - addr_block1 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase1)); - real_addr_block1 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)((struct mdesc *)s_heap)->heapbase)); - for(j=0; j < (size_t) (BLOCKSIZE >> heapinfo1[i].type); j++){ - if(i1== heaplimit){ - if(heapinfo1[i].busy_frag.frag_size[j] > 0){ - if(equals_to1[i][j] == NULL){ + if(state->heapinfo1[i].type > 0){ + addr_block1 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)state->heapbase1)); + real_addr_block1 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)((struct mdesc *)state->s_heap)->heapbase)); + for(j=0; j < (size_t) (BLOCKSIZE >> state->heapinfo1[i].type); j++){ + if(i1== state->heaplimit){ + if(state->heapinfo1[i].busy_frag.frag_size[j] > 0){ + if(state->equals_to1[i][j] == NULL){ if(XBT_LOG_ISENABLED(mm_diff, xbt_log_priority_debug)){ - addr_frag1 = (void*) ((char *)addr_block1 + (j << heapinfo1[i].type)); - real_addr_frag1 = (void*) ((char *)real_addr_block1 + (j << ((struct mdesc *)s_heap)->heapinfo[i].type)); - XBT_DEBUG("Block %zu, Fragment %zu (%p - %p) not found (size used = %zd)", i, j, addr_frag1, real_addr_frag1, heapinfo1[i].busy_frag.frag_size[j]); + addr_frag1 = (void*) ((char *)addr_block1 + (j << state->heapinfo1[i].type)); + real_addr_frag1 = (void*) ((char *)real_addr_block1 + (j << ((struct mdesc *)state->s_heap)->heapinfo[i].type)); + XBT_DEBUG("Block %zu, Fragment %zu (%p - %p) not found (size used = %zd)", i, j, addr_frag1, real_addr_frag1, state->heapinfo1[i].busy_frag.frag_size[j]); //mmalloc_backtrace_fragment_display((void*)heapinfo1, i, j); } nb_diff1++; @@ -649,19 +653,19 @@ int mmalloc_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dict_t all_ty i++; } - if(i1 == heaplimit) + if(i1 == state->heaplimit) XBT_DEBUG("Number of blocks/fragments not found in heap1 : %d", nb_diff1); i = 1; - while(i<=heaplimit){ - if(heapinfo2[i].type == 0){ - if(i1 == heaplimit){ - if(heapinfo2[i].busy_block.busy_size > 0){ - if(equals_to2[i][0] == NULL){ + while(i<=state->heaplimit){ + if(state->heapinfo2[i].type == 0){ + if(i1 == state->heaplimit){ + if(state->heapinfo2[i].busy_block.busy_size > 0){ + if(state->equals_to2[i][0] == NULL){ if(XBT_LOG_ISENABLED(mm_diff, xbt_log_priority_debug)){ - addr_block2 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase2)); - XBT_DEBUG("Block %zu (%p) not found (size used = %zu)", i, addr_block2, heapinfo2[i].busy_block.busy_size); + addr_block2 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)state->heapbase2)); + XBT_DEBUG("Block %zu (%p) not found (size used = %zu)", i, addr_block2, state->heapinfo2[i].busy_block.busy_size); //mmalloc_backtrace_block_display((void*)heapinfo2, i); } nb_diff2++; @@ -669,17 +673,17 @@ int mmalloc_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dict_t all_ty } } } - if(heapinfo2[i].type > 0){ - addr_block2 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase2)); - real_addr_block2 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)((struct mdesc *)s_heap)->heapbase)); - for(j=0; j < (size_t) (BLOCKSIZE >> heapinfo2[i].type); j++){ - if(i1 == heaplimit){ - if(heapinfo2[i].busy_frag.frag_size[j] > 0){ - if(equals_to2[i][j] == NULL){ + if(state->heapinfo2[i].type > 0){ + addr_block2 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)state->heapbase2)); + real_addr_block2 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)((struct mdesc *)state->s_heap)->heapbase)); + for(j=0; j < (size_t) (BLOCKSIZE >> state->heapinfo2[i].type); j++){ + if(i1 == state->heaplimit){ + if(state->heapinfo2[i].busy_frag.frag_size[j] > 0){ + if(state->equals_to2[i][j] == NULL){ if(XBT_LOG_ISENABLED(mm_diff, xbt_log_priority_debug)){ - addr_frag2 = (void*) ((char *)addr_block2 + (j << heapinfo2[i].type)); - real_addr_frag2 = (void*) ((char *)real_addr_block2 + (j << ((struct mdesc *)s_heap)->heapinfo[i].type)); - XBT_DEBUG( "Block %zu, Fragment %zu (%p - %p) not found (size used = %zd)", i, j, addr_frag2, real_addr_frag2, heapinfo2[i].busy_frag.frag_size[j]); + addr_frag2 = (void*) ((char *)addr_block2 + (j << state->heapinfo2[i].type)); + real_addr_frag2 = (void*) ((char *)real_addr_block2 + (j << ((struct mdesc *)state->s_heap)->heapinfo[i].type)); + XBT_DEBUG( "Block %zu, Fragment %zu (%p - %p) not found (size used = %zd)", i, j, addr_frag2, real_addr_frag2, state->heapinfo2[i].busy_frag.frag_size[j]); //mmalloc_backtrace_fragment_display((void*)heapinfo2, i, j); } nb_diff2++; @@ -691,7 +695,7 @@ int mmalloc_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dict_t all_ty i++; } - if(i1 == heaplimit) + if(i1 == state->heaplimit) XBT_DEBUG("Number of blocks/fragments not found in heap2 : %d", nb_diff2); xbt_dynar_free(&previous); @@ -700,17 +704,18 @@ int mmalloc_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dict_t all_ty return ((nb_diff1 > 0) || (nb_diff2 > 0)); } -static int compare_heap_area_without_type(void *real_area1, void *real_area2, void *area1, void *area2, xbt_dynar_t previous, xbt_dict_t all_types, xbt_dict_t other_types, int size, int check_ignore){ +static int compare_heap_area_without_type(struct s_mm_diff *state, void *real_area1, void *real_area2, void *area1, void *area2, xbt_dynar_t previous, mc_object_info_t info, mc_object_info_t other_info, int size, int check_ignore){ int i = 0; void *addr_pointed1, *addr_pointed2; - int pointer_align, ignore1, ignore2, res_compare; + int pointer_align, res_compare; + ssize_t ignore1, ignore2; while(i 0){ - if((ignore1 = heap_comparison_ignore_size(to_ignore1, (char *)real_area1 + i)) != -1){ - if((ignore2 = heap_comparison_ignore_size(to_ignore2, (char *)real_area2 + i)) == ignore1){ + if((ignore1 = heap_comparison_ignore_size(state->to_ignore1, (char *)real_area1 + i)) != -1){ + if((ignore2 = heap_comparison_ignore_size(state->to_ignore2, (char *)real_area2 + i)) == ignore1){ if(ignore1 == 0){ check_ignore--; return 0; @@ -732,9 +737,9 @@ static int compare_heap_area_without_type(void *real_area1, void *real_area2, vo if(addr_pointed1 > maestro_stack_start && addr_pointed1 < maestro_stack_end && addr_pointed2 > maestro_stack_start && addr_pointed2 < maestro_stack_end){ i = pointer_align + sizeof(void *); continue; - }else if((addr_pointed1 > s_heap) && ((char *)addr_pointed1 < (char *)s_heap + STD_HEAP_SIZE) - && (addr_pointed2 > s_heap) && ((char *)addr_pointed2 < (char *)s_heap + STD_HEAP_SIZE)){ - res_compare = compare_heap_area(addr_pointed1, addr_pointed2, previous, all_types, other_types, NULL, 0); + }else if((addr_pointed1 > state->s_heap) && ((char *)addr_pointed1 < (char *)state->s_heap + STD_HEAP_SIZE) + && (addr_pointed2 > state->s_heap) && ((char *)addr_pointed2 < (char *)state->s_heap + STD_HEAP_SIZE)){ + res_compare = compare_heap_area(addr_pointed1, addr_pointed2, previous, info, other_info, NULL, 0); if(res_compare == 1){ return res_compare; } @@ -754,103 +759,94 @@ static int compare_heap_area_without_type(void *real_area1, void *real_area2, vo } - -static int compare_heap_area_with_type(void *real_area1, void *real_area2, void *area1, void *area2, - xbt_dynar_t previous, xbt_dict_t all_types, xbt_dict_t other_types, char *type_id, +// area_size is either a byte_size or an elements_count?& +static int compare_heap_area_with_type(struct s_mm_diff *state, void *real_area1, void *real_area2, void *area1, void *area2, + xbt_dynar_t previous, mc_object_info_t info, mc_object_info_t other_info, char *type_id, int area_size, int check_ignore, int pointer_level){ if(is_stack(real_area1) && is_stack(real_area2)) return 0; - size_t ignore1, ignore2; + ssize_t ignore1, ignore2; - if((check_ignore > 0) && ((ignore1 = heap_comparison_ignore_size(to_ignore1, real_area1)) > 0) && ((ignore2 = heap_comparison_ignore_size(to_ignore2, real_area2)) == ignore1)){ + if((check_ignore > 0) && ((ignore1 = heap_comparison_ignore_size(state->to_ignore1, real_area1)) > 0) && ((ignore2 = heap_comparison_ignore_size(state->to_ignore2, real_area2)) == ignore1)){ return 0; } - dw_type_t type = xbt_dict_get_or_null(all_types, type_id); + dw_type_t type = xbt_dict_get_or_null(info->types, type_id); dw_type_t subtype, subsubtype; int res, elm_size, i, switch_types = 0; unsigned int cursor = 0; dw_type_t member; void *addr_pointed1, *addr_pointed2;; - char *type_desc; switch(type->type){ - case e_dw_base_type: - if(strcmp(type->name, "char") == 0){ /* String, hence random (arbitrary ?) size */ + case DW_TAG_base_type: + if(type->name!=NULL && strcmp(type->name, "char") == 0){ /* String, hence random (arbitrary ?) size */ if(real_area1 == real_area2) return -1; else return (memcmp(area1, area2, area_size) != 0); }else{ - if(area_size != -1 && type->size != area_size) + if(area_size != -1 && type->byte_size != area_size) return -1; else{ - return (memcmp(area1, area2, type->size) != 0); + return (memcmp(area1, area2, type->byte_size) != 0); } } break; - case e_dw_enumeration_type: - if(area_size != -1 && type->size != area_size) + case DW_TAG_enumeration_type: + if(area_size != -1 && type->byte_size != area_size) return -1; else - return (memcmp(area1, area2, type->size) != 0); - break; - case e_dw_typedef: - return compare_heap_area_with_type(real_area1, real_area2, area1, area2, previous, all_types, other_types, type->dw_type_id, area_size, check_ignore, pointer_level); + return (memcmp(area1, area2, type->byte_size) != 0); break; - case e_dw_const_type: - return 0; + case DW_TAG_typedef: + case DW_TAG_const_type: + case DW_TAG_volatile_type: + return compare_heap_area_with_type(state, real_area1, real_area2, area1, area2, previous, info, other_info, type->dw_type_id, area_size, check_ignore, pointer_level); break; - case e_dw_array_type: - subtype = xbt_dict_get_or_null(all_types, type->dw_type_id); + case DW_TAG_array_type: + subtype = xbt_dict_get_or_null(info->types, type->dw_type_id); switch(subtype->type){ - case e_dw_base_type: - case e_dw_enumeration_type: - case e_dw_pointer_type: - case e_dw_structure_type: - case e_dw_union_type: - if(subtype->size == 0){ /*declaration of the type, need the complete description */ - type_desc = get_type_description(all_types, subtype->name); - if(type_desc){ - subtype = xbt_dict_get_or_null(all_types, type_desc); - }else{ - subtype = xbt_dict_get_or_null(other_types, get_type_description(other_types, subtype->name)); + 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->size; + elm_size = subtype->byte_size; break; - case e_dw_typedef: - case e_dw_volatile_type: - subsubtype = xbt_dict_get_or_null(all_types, subtype->dw_type_id); - if(subsubtype->size == 0){ /*declaration of the type, need the complete description */ - type_desc = get_type_description(all_types, subsubtype->name); - if(type_desc){ - subsubtype = xbt_dict_get_or_null(all_types, type_desc); - }else{ - subsubtype = xbt_dict_get_or_null(other_types, get_type_description(other_types, subtype->name)); + // TODO, just remove the type indirection? + 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, subtype->name); switch_types = 1; - } } - elm_size = subsubtype->size; + elm_size = subsubtype->byte_size; break; default : return 0; break; } - for(i=0; isize; i++){ + for(i=0; ielement_count; i++){ + // TODO, add support for variable stride (DW_AT_byte_stride) if(switch_types) - res = compare_heap_area_with_type((char *)real_area1 + (i*elm_size), (char *)real_area2 + (i*elm_size), (char *)area1 + (i*elm_size), (char *)area2 + (i*elm_size), previous, other_types, all_types, type->dw_type_id, type->size, check_ignore, pointer_level); + res = compare_heap_area_with_type(state, (char *)real_area1 + (i*elm_size), (char *)real_area2 + (i*elm_size), (char *)area1 + (i*elm_size), (char *)area2 + (i*elm_size), previous, other_info, info, type->dw_type_id, subtype->byte_size, check_ignore, pointer_level); else - res = compare_heap_area_with_type((char *)real_area1 + (i*elm_size), (char *)real_area2 + (i*elm_size), (char *)area1 + (i*elm_size), (char *)area2 + (i*elm_size), previous, all_types, other_types, type->dw_type_id, type->size, check_ignore, pointer_level); + res = compare_heap_area_with_type(state, (char *)real_area1 + (i*elm_size), (char *)real_area2 + (i*elm_size), (char *)area1 + (i*elm_size), (char *)area2 + (i*elm_size), previous, info, other_info, type->dw_type_id, subtype->byte_size, check_ignore, pointer_level); if(res == 1) return res; } break; - case e_dw_pointer_type: - if(type->dw_type_id && ((dw_type_t)xbt_dict_get_or_null(all_types, type->dw_type_id))->type == e_dw_subroutine_type){ + 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);; @@ -860,8 +856,8 @@ static int compare_heap_area_with_type(void *real_area1, void *real_area2, void for(i=0; i<(area_size/sizeof(void *)); i++){ addr_pointed1 = *((void **)((char *)area1 + (i*sizeof(void *)))); addr_pointed2 = *((void **)((char *)area2 + (i*sizeof(void *)))); - if(addr_pointed1 > s_heap && (char *)addr_pointed1 < (char*) s_heap + STD_HEAP_SIZE && addr_pointed2 > s_heap && (char *)addr_pointed2 < (char*) s_heap + STD_HEAP_SIZE) - res = compare_heap_area(addr_pointed1, addr_pointed2, previous, all_types, other_types, type->dw_type_id, pointer_level); + if(addr_pointed1 > state->s_heap && (char *)addr_pointed1 < (char*) state->s_heap + STD_HEAP_SIZE && addr_pointed2 > state->s_heap && (char *)addr_pointed2 < (char*) state->s_heap + STD_HEAP_SIZE) + res = compare_heap_area(addr_pointed1, addr_pointed2, previous, info, other_info, type->dw_type_id, pointer_level); else res = (addr_pointed1 != addr_pointed2); if(res == 1) @@ -870,30 +866,30 @@ static int compare_heap_area_with_type(void *real_area1, void *real_area2, void }else{ addr_pointed1 = *((void **)(area1)); addr_pointed2 = *((void **)(area2)); - if(addr_pointed1 > s_heap && (char *)addr_pointed1 < (char*) s_heap + STD_HEAP_SIZE && addr_pointed2 > s_heap && (char *)addr_pointed2 < (char*) s_heap + STD_HEAP_SIZE) - return compare_heap_area(addr_pointed1, addr_pointed2, previous, all_types, other_types, type->dw_type_id, pointer_level); + if(addr_pointed1 > state->s_heap && (char *)addr_pointed1 < (char*) state->s_heap + STD_HEAP_SIZE && addr_pointed2 > state->s_heap && (char *)addr_pointed2 < (char*) state->s_heap + STD_HEAP_SIZE) + return compare_heap_area(addr_pointed1, addr_pointed2, previous, info, other_info, type->dw_type_id, pointer_level); else return (addr_pointed1 != addr_pointed2); } } break; - case e_dw_structure_type: - if(type->size == 0){ /*declaration of the structure, need the complete description */ - type_desc = get_type_description(all_types, type->name); - if(type_desc){ - type = xbt_dict_get_or_null(all_types, type_desc); + case DW_TAG_structure_type: + if(type->byte_size == 0){ /*declaration of the structure, need the complete description */ + dw_type_t full_type = xbt_dict_get_or_null(info->types_by_name, type->name); + if(full_type){ + type = full_type; }else{ - type = xbt_dict_get_or_null(other_types, get_type_description(other_types, type->name)); + type = xbt_dict_get_or_null(other_info->types_by_name, type->name); switch_types = 1; } } - if(area_size != -1 && type->size != area_size){ - if(area_size>type->size && area_size%type->size == 0){ - for(i=0; i<(area_size/type->size); i++){ + if(area_size != -1 && type->byte_size != area_size){ + if(area_size>type->byte_size && area_size%type->byte_size == 0){ + for(i=0; i<(area_size/type->byte_size); i++){ if(switch_types) - res = compare_heap_area_with_type((char *)real_area1 + (i*type->size), (char *)real_area2 + (i*type->size), (char *)area1 + (i*type->size), (char *)area2 + (i*type->size), previous, other_types, all_types, type_id, -1, check_ignore, 0); + res = compare_heap_area_with_type(state, (char *)real_area1 + (i*type->byte_size), (char *)real_area2 + (i*type->byte_size), (char *)area1 + (i*type->byte_size), (char *)area2 + (i*type->byte_size), previous, other_info, info, type_id, -1, check_ignore, 0); else - res = compare_heap_area_with_type((char *)real_area1 + (i*type->size), (char *)real_area2 + (i*type->size), (char *)area1 + (i*type->size), (char *)area2 + (i*type->size), previous, all_types, other_types, type_id, -1, check_ignore, 0); + res = compare_heap_area_with_type(state, (char *)real_area1 + (i*type->byte_size), (char *)real_area2 + (i*type->byte_size), (char *)area1 + (i*type->byte_size), (char *)area2 + (i*type->byte_size), previous, info, other_info, type_id, -1, check_ignore, 0); if(res == 1) return res; } @@ -904,20 +900,17 @@ static int compare_heap_area_with_type(void *real_area1, void *real_area2, void cursor = 0; xbt_dynar_foreach(type->members, cursor, member){ if(switch_types) - res = compare_heap_area_with_type((char *)real_area1 + member->offset, (char *)real_area2 + member->offset, (char *)area1 + member->offset, (char *)area2 + member->offset, previous, other_types, all_types, member->dw_type_id, -1, check_ignore, 0); + res = compare_heap_area_with_type(state, (char *)real_area1 + member->offset, (char *)real_area2 + member->offset, (char *)area1 + member->offset, (char *)area2 + member->offset, previous, other_info, info, member->dw_type_id, -1, check_ignore, 0); else - res = compare_heap_area_with_type((char *)real_area1 + member->offset, (char *)real_area2 + member->offset, (char *)area1 + member->offset, (char *)area2 + member->offset, previous, all_types, other_types, member->dw_type_id, -1, check_ignore, 0); + res = compare_heap_area_with_type(state, (char *)real_area1 + member->offset, (char *)real_area2 + member->offset, (char *)area1 + member->offset, (char *)area2 + member->offset, previous, info, other_info, member->dw_type_id, -1, check_ignore, 0); if(res == 1){ return res; } } } break; - case e_dw_union_type: - return compare_heap_area_without_type(real_area1, real_area2, area1, area2, previous, all_types, other_types, type->size, check_ignore); - break; - case e_dw_volatile_type: - return compare_heap_area_with_type(real_area1, real_area2, area1, area2, previous, all_types, other_types, type->dw_type_id, area_size, check_ignore, pointer_level); + case DW_TAG_union_type: + return compare_heap_area_without_type(state, real_area1, real_area2, area1, area2, previous, info, other_info, type->byte_size, check_ignore); break; default: break; @@ -927,37 +920,36 @@ static int compare_heap_area_with_type(void *real_area1, void *real_area2, void } -static char* get_offset_type(char* type_id, int offset, xbt_dict_t all_types, xbt_dict_t other_types, int area_size, int *switch_type){ - dw_type_t type = xbt_dict_get_or_null(all_types, type_id); +static char* get_offset_type(char* type_id, int offset, mc_object_info_t info, mc_object_info_t other_info, int area_size, int *switch_type){ + dw_type_t type = xbt_dict_get_or_null(info->types, type_id); if(type == NULL){ - type = xbt_dict_get_or_null(other_types, type_id); + type = xbt_dict_get_or_null(other_info->types, type_id); *switch_type = 1; } - char* type_desc; switch(type->type){ - case e_dw_structure_type : - if(type->size == 0){ /*declaration of the structure, need the complete description */ + case DW_TAG_structure_type : + if(type->byte_size == 0){ /*declaration of the structure, need the complete description */ if(*switch_type == 0){ - type_desc = get_type_description(all_types, type->name); - if(type_desc){ - type = xbt_dict_get_or_null(all_types, type_desc); + dw_type_t full_type = xbt_dict_get_or_null(info->types_by_name, type->name); + if(full_type){ + type = full_type; }else{ - type = xbt_dict_get_or_null(other_types, get_type_description(other_types, type->name)); + type = xbt_dict_get_or_null(other_info->types_by_name, type->name); *switch_type = 1; } }else{ - type_desc = get_type_description(other_types, type->name); - if(type_desc){ - type = xbt_dict_get_or_null(other_types, type_desc); + dw_type_t full_type = xbt_dict_get_or_null(other_info->types_by_name, type->name); + if(full_type){ + type = full_type; }else{ - type = xbt_dict_get_or_null(all_types, get_type_description(other_types, type->name)); + type = xbt_dict_get_or_null(info->types_by_name, type->name); *switch_type = 0; } } } - if(area_size != -1 && type->size != area_size){ - if(area_size>type->size && area_size%type->size == 0) + if(area_size != -1 && type->byte_size != area_size){ + if(area_size>type->byte_size && area_size%type->byte_size == 0) return type_id; else return NULL; @@ -978,7 +970,9 @@ static char* get_offset_type(char* type_id, int offset, xbt_dict_t all_types, xb } } -int compare_heap_area(void *area1, void* area2, xbt_dynar_t previous, xbt_dict_t all_types, xbt_dict_t other_types, char *type_id, int pointer_level){ +int compare_heap_area(void *area1, void* area2, xbt_dynar_t previous, mc_object_info_t info, mc_object_info_t other_info, char *type_id, int pointer_level){ + + struct s_mm_diff* state = mm_diff_info; int res_compare; ssize_t block1, frag1, block2, frag2; @@ -988,7 +982,6 @@ int compare_heap_area(void *area1, void* area2, xbt_dynar_t previous, xbt_dict_t void *addr_block1, *addr_block2, *addr_frag1, *addr_frag2, *real_addr_block1, *real_addr_block2, *real_addr_frag1, *real_addr_frag2; void *area1_to_compare, *area2_to_compare; dw_type_t type = NULL; - char *type_desc; int type_size = -1; int offset1 =0, offset2 = 0; int new_size1 = -1, new_size2 = -1; @@ -1002,64 +995,64 @@ int compare_heap_area(void *area1, void* area2, xbt_dynar_t previous, xbt_dict_t match_pairs = 1; } - block1 = ((char*)area1 - (char*)((xbt_mheap_t)s_heap)->heapbase) / BLOCKSIZE + 1; - block2 = ((char*)area2 - (char*)((xbt_mheap_t)s_heap)->heapbase) / BLOCKSIZE + 1; + block1 = ((char*)area1 - (char*)((xbt_mheap_t)state->s_heap)->heapbase) / BLOCKSIZE + 1; + block2 = ((char*)area2 - (char*)((xbt_mheap_t)state->s_heap)->heapbase) / BLOCKSIZE + 1; if(is_block_stack((int)block1) && is_block_stack((int)block2)){ add_heap_area_pair(previous, block1, -1, block2, -1); if(match_pairs){ - match_equals(previous); + match_equals(state, previous); xbt_dynar_free(&previous); } return 0; } - if(((char *)area1 < (char*)((xbt_mheap_t)s_heap)->heapbase) || (block1 > heapsize1) || (block1 < 1) || ((char *)area2 < (char*)((xbt_mheap_t)s_heap)->heapbase) || (block2 > heapsize2) || (block2 < 1)){ + if(((char *)area1 < (char*)((xbt_mheap_t)state->s_heap)->heapbase) || (block1 > state->heapsize1) || (block1 < 1) || ((char *)area2 < (char*)((xbt_mheap_t)state->s_heap)->heapbase) || (block2 > state->heapsize2) || (block2 < 1)){ if(match_pairs){ xbt_dynar_free(&previous); } return 1; } - addr_block1 = ((void*) (((ADDR2UINT(block1)) - 1) * BLOCKSIZE + (char*)heapbase1)); - addr_block2 = ((void*) (((ADDR2UINT(block2)) - 1) * BLOCKSIZE + (char*)heapbase2)); + addr_block1 = ((void*) (((ADDR2UINT(block1)) - 1) * BLOCKSIZE + (char*)state->heapbase1)); + addr_block2 = ((void*) (((ADDR2UINT(block2)) - 1) * BLOCKSIZE + (char*)state->heapbase2)); - real_addr_block1 = ((void*) (((ADDR2UINT(block1)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)s_heap)->heapbase)); - real_addr_block2 = ((void*) (((ADDR2UINT(block2)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)s_heap)->heapbase)); + real_addr_block1 = ((void*) (((ADDR2UINT(block1)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)state->s_heap)->heapbase)); + real_addr_block2 = ((void*) (((ADDR2UINT(block2)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)state->s_heap)->heapbase)); if(type_id){ - type = xbt_dict_get_or_null(all_types, type_id); - if(type->size == 0){ - if(type->dw_type_id == NULL){ - type_desc = get_type_description(all_types, type->name); - if(type_desc) - type = xbt_dict_get_or_null(all_types, type_desc); + type = xbt_dict_get_or_null(info->types, type_id); + if(type->byte_size == 0){ + if(type->subtype == NULL){ + dw_type_t full_type = xbt_dict_get_or_null(info->types_by_name, type->name); + if(full_type) + type = full_type; else - type = xbt_dict_get_or_null(other_types, get_type_description(other_types, type->name)); + type = xbt_dict_get_or_null(other_info->types_by_name, type->name); }else{ - type = xbt_dict_get_or_null(all_types, type->dw_type_id); + type = type->subtype; } } - if((type->type == e_dw_pointer_type) || ((type->type == e_dw_base_type) && (!strcmp(type->name, "char")))) + if((type->byte_size == DW_TAG_pointer_type) || ((type->type == DW_TAG_base_type) && type->name!=NULL && (!strcmp(type->name, "char")))) type_size = -1; else - type_size = type->size; + type_size = type->byte_size; } - if((heapinfo1[block1].type == -1) && (heapinfo2[block2].type == -1)){ /* Free block */ + if((state->heapinfo1[block1].type == -1) && (state->heapinfo2[block2].type == -1)){ /* Free block */ if(match_pairs){ - match_equals(previous); + match_equals(state, previous); xbt_dynar_free(&previous); } return 0; - }else if((heapinfo1[block1].type == 0) && (heapinfo2[block2].type == 0)){ /* Complete block */ + }else if((state->heapinfo1[block1].type == 0) && (state->heapinfo2[block2].type == 0)){ /* Complete block */ - if(equals_to1[block1][0] != NULL && equals_to2[block2][0] != NULL){ - if(equal_blocks(block1, block2)){ + if(state->equals_to1[block1][0] != NULL && state->equals_to2[block2][0] != NULL){ + if(equal_blocks(state, block1, block2)){ if(match_pairs){ - match_equals(previous); + match_equals(state, previous); xbt_dynar_free(&previous); } return 0; @@ -1067,23 +1060,25 @@ int compare_heap_area(void *area1, void* area2, xbt_dynar_t previous, xbt_dict_t } if(type_size != -1){ - if(type_size != heapinfo1[block1].busy_block.busy_size && type_size != heapinfo2[block2].busy_block.busy_size && !strcmp(type->name, "s_smx_context")){ + if(type_size != state->heapinfo1[block1].busy_block.busy_size + && type_size != state->heapinfo2[block2].busy_block.busy_size + && type->name!=NULL && !strcmp(type->name, "s_smx_context")){ if(match_pairs){ - match_equals(previous); + match_equals(state, previous); xbt_dynar_free(&previous); } return -1; } } - if(heapinfo1[block1].busy_block.size != heapinfo2[block2].busy_block.size){ + if(state->heapinfo1[block1].busy_block.size != state->heapinfo2[block2].busy_block.size){ if(match_pairs){ xbt_dynar_free(&previous); } return 1; } - if(heapinfo1[block1].busy_block.busy_size != heapinfo2[block2].busy_block.busy_size){ + if(state->heapinfo1[block1].busy_block.busy_size != state->heapinfo2[block2].busy_block.busy_size){ if(match_pairs){ xbt_dynar_free(&previous); } @@ -1092,24 +1087,24 @@ int compare_heap_area(void *area1, void* area2, xbt_dynar_t previous, xbt_dict_t if(!add_heap_area_pair(previous, block1, -1, block2, -1)){ if(match_pairs){ - match_equals(previous); + match_equals(state, previous); xbt_dynar_free(&previous); } return 0; } - size = heapinfo1[block1].busy_block.busy_size; + size = state->heapinfo1[block1].busy_block.busy_size; if(type_id != NULL){ - xbt_free(types1[block1][0]); - xbt_free(types2[block2][0]); - types1[block1][0] = strdup(type_id); - types2[block2][0] = strdup(type_id); + xbt_free(state->types1[block1][0]); + xbt_free(state->types2[block2][0]); + state->types1[block1][0] = strdup(type_id); + state->types2[block2][0] = strdup(type_id); } if(size <= 0){ if(match_pairs){ - match_equals(previous); + match_equals(state, previous); xbt_dynar_free(&previous); } return 0; @@ -1121,51 +1116,51 @@ int compare_heap_area(void *area1, void* area2, xbt_dynar_t previous, xbt_dict_t area1_to_compare = addr_block1; area2_to_compare = addr_block2; - if((heapinfo1[block1].busy_block.ignore > 0) && (heapinfo2[block2].busy_block.ignore == heapinfo1[block1].busy_block.ignore)) - check_ignore = heapinfo1[block1].busy_block.ignore; + if((state->heapinfo1[block1].busy_block.ignore > 0) && (state->heapinfo2[block2].busy_block.ignore == state->heapinfo1[block1].busy_block.ignore)) + check_ignore = state->heapinfo1[block1].busy_block.ignore; - }else if((heapinfo1[block1].type > 0) && (heapinfo2[block2].type > 0)){ /* Fragmented block */ + }else if((state->heapinfo1[block1].type > 0) && (state->heapinfo2[block2].type > 0)){ /* Fragmented block */ - frag1 = ((uintptr_t) (ADDR2UINT (area1) % (BLOCKSIZE))) >> heapinfo1[block1].type; - frag2 = ((uintptr_t) (ADDR2UINT (area2) % (BLOCKSIZE))) >> heapinfo2[block2].type; + frag1 = ((uintptr_t) (ADDR2UINT (area1) % (BLOCKSIZE))) >> state->heapinfo1[block1].type; + frag2 = ((uintptr_t) (ADDR2UINT (area2) % (BLOCKSIZE))) >> state->heapinfo2[block2].type; - addr_frag1 = (void*) ((char *)addr_block1 + (frag1 << heapinfo1[block1].type)); - addr_frag2 = (void*) ((char *)addr_block2 + (frag2 << heapinfo2[block2].type)); + addr_frag1 = (void*) ((char *)addr_block1 + (frag1 << state->heapinfo1[block1].type)); + addr_frag2 = (void*) ((char *)addr_block2 + (frag2 << state->heapinfo2[block2].type)); - real_addr_frag1 = (void*) ((char *)real_addr_block1 + (frag1 << ((xbt_mheap_t)s_heap)->heapinfo[block1].type)); - real_addr_frag2 = (void*) ((char *)real_addr_block2 + (frag2 << ((xbt_mheap_t)s_heap)->heapinfo[block2].type)); + real_addr_frag1 = (void*) ((char *)real_addr_block1 + (frag1 << ((xbt_mheap_t)state->s_heap)->heapinfo[block1].type)); + real_addr_frag2 = (void*) ((char *)real_addr_block2 + (frag2 << ((xbt_mheap_t)state->s_heap)->heapinfo[block2].type)); if(type_size != -1){ - if(heapinfo1[block1].busy_frag.frag_size[frag1] == -1 || heapinfo2[block2].busy_frag.frag_size[frag2] == -1){ + if(state->heapinfo1[block1].busy_frag.frag_size[frag1] == -1 || state->heapinfo2[block2].busy_frag.frag_size[frag2] == -1){ if(match_pairs){ - match_equals(previous); + match_equals(state, previous); xbt_dynar_free(&previous); } return -1; } - if(type_size != heapinfo1[block1].busy_frag.frag_size[frag1] || type_size != heapinfo2[block2].busy_frag.frag_size[frag2]){ + if(type_size != state->heapinfo1[block1].busy_frag.frag_size[frag1]|| type_size != state->heapinfo2[block2].busy_frag.frag_size[frag2]){ if(match_pairs){ - match_equals(previous); + match_equals(state, previous); xbt_dynar_free(&previous); } return -1; } } - if(equals_to1[block1][frag1] != NULL && equals_to2[block2][frag2] != NULL){ - if(equal_fragments(block1, frag1, block2, frag2)){ + if(state->equals_to1[block1][frag1] != NULL && state->equals_to2[block2][frag2] != NULL){ + if(equal_fragments(state, block1, frag1, block2, frag2)){ if(match_pairs){ - match_equals(previous); + match_equals(state, previous); xbt_dynar_free(&previous); } return 0; } } - if(heapinfo1[block1].busy_frag.frag_size[frag1] != heapinfo2[block2].busy_frag.frag_size[frag2]){ + if(state->heapinfo1[block1].busy_frag.frag_size[frag1] != state->heapinfo2[block2].busy_frag.frag_size[frag2]){ if(type_size == -1){ if(match_pairs){ - match_equals(previous); + match_equals(state, previous); xbt_dynar_free(&previous); } return -1; @@ -1177,30 +1172,30 @@ int compare_heap_area(void *area1, void* area2, xbt_dynar_t previous, xbt_dict_t } } - size = heapinfo1[block1].busy_frag.frag_size[frag1]; + size = state->heapinfo1[block1].busy_frag.frag_size[frag1]; if(type_id != NULL){ - xbt_free(types1[block1][frag1]); - xbt_free(types2[block2][frag2]); - types1[block1][frag1] = strdup(type_id); - types2[block2][frag2] = strdup(type_id); + xbt_free(state->types1[block1][frag1]); + xbt_free(state->types2[block2][frag2]); + state->types1[block1][frag1] = strdup(type_id); + state->types2[block2][frag2] = strdup(type_id); } if(real_addr_frag1 != area1 || real_addr_frag2 != area2){ offset1 = (char *)area1 - (char *)real_addr_frag1; offset2 = (char *)area2 - (char *)real_addr_frag2; - if(types1[block1][frag1] != NULL && types2[block2][frag2] != NULL){ - new_type_id1 = get_offset_type(types1[block1][frag1], offset1, all_types, other_types, size, &switch_type); - new_type_id2 = get_offset_type(types2[block2][frag2], offset1, all_types, other_types, size, &switch_type); - }else if(types1[block1][frag1] != NULL){ - new_type_id1 = get_offset_type(types1[block1][frag1], offset1, all_types, other_types, size, &switch_type); - new_type_id2 = get_offset_type(types1[block1][frag1], offset2, all_types, other_types, size, &switch_type); - }else if(types2[block2][frag2] != NULL){ - new_type_id1 = get_offset_type(types2[block2][frag2], offset1, all_types, other_types, size, &switch_type); - new_type_id2 = get_offset_type(types2[block2][frag2], offset2, all_types, other_types, size, &switch_type); + if(state->types1[block1][frag1] != NULL && state->types2[block2][frag2] != NULL){ + new_type_id1 = get_offset_type(state->types1[block1][frag1], offset1, info, other_info, size, &switch_type); + new_type_id2 = get_offset_type(state->types2[block2][frag2], offset1, info, other_info, size, &switch_type); + }else if(state->types1[block1][frag1] != NULL){ + new_type_id1 = get_offset_type(state->types1[block1][frag1], offset1, info, other_info, size, &switch_type); + new_type_id2 = get_offset_type(state->types1[block1][frag1], offset2, info, other_info, size, &switch_type); + }else if(state->types2[block2][frag2] != NULL){ + new_type_id1 = get_offset_type(state->types2[block2][frag2], offset1, info, other_info, size, &switch_type); + new_type_id2 = get_offset_type(state->types2[block2][frag2], offset2, info, other_info, size, &switch_type); }else{ if(match_pairs){ - match_equals(previous); + match_equals(state, previous); xbt_dynar_free(&previous); } return -1; @@ -1208,27 +1203,27 @@ int compare_heap_area(void *area1, void* area2, xbt_dynar_t previous, xbt_dict_t if(new_type_id1 != NULL && new_type_id2 != NULL && !strcmp(new_type_id1, new_type_id2)){ if(switch_type){ - type = xbt_dict_get_or_null(other_types, new_type_id1); - while(type->size == 0 && type->dw_type_id != NULL) - type = xbt_dict_get_or_null(other_types, type->dw_type_id); - new_size1 = type->size; - type = xbt_dict_get_or_null(other_types, new_type_id2); - while(type->size == 0 && type->dw_type_id != NULL) - type = xbt_dict_get_or_null(other_types, type->dw_type_id); - new_size2 = type->size; + type = xbt_dict_get_or_null(other_info->types, new_type_id1); + while(type->byte_size == 0 && type->dw_type_id != NULL) + type = xbt_dict_get_or_null(other_info->types, type->dw_type_id); + new_size1 = type->byte_size; + type = xbt_dict_get_or_null(other_info->types, new_type_id2); + while(type->byte_size == 0 && type->dw_type_id != NULL) + type = xbt_dict_get_or_null(other_info->types, type->dw_type_id); + new_size2 = type->byte_size; }else{ - type = xbt_dict_get_or_null(all_types, new_type_id1); - while(type->size == 0 && type->dw_type_id != NULL) - type = xbt_dict_get_or_null(all_types, type->dw_type_id); - new_size1 = type->size; - type = xbt_dict_get_or_null(all_types, new_type_id2); - while(type->size == 0 && type->dw_type_id != NULL) - type = xbt_dict_get_or_null(all_types, type->dw_type_id); - new_size2 = type->size; + type = xbt_dict_get_or_null(info->types, new_type_id1); + while(type->byte_size == 0 && type->dw_type_id != NULL) + type = xbt_dict_get_or_null(info->types, type->dw_type_id); + new_size1 = type->byte_size; + type = xbt_dict_get_or_null(info->types, new_type_id2); + while(type->byte_size == 0 && type->dw_type_id != NULL) + type = xbt_dict_get_or_null(info->types, type->dw_type_id); + new_size2 = type->byte_size; } }else{ if(match_pairs){ - match_equals(previous); + match_equals(state, previous); xbt_dynar_free(&previous); } return -1; @@ -1246,7 +1241,7 @@ int compare_heap_area(void *area1, void* area2, xbt_dynar_t previous, xbt_dict_t if(offset1 == 0 && offset2 == 0){ if(!add_heap_area_pair(previous, block1, frag1, block2, frag2)){ if(match_pairs){ - match_equals(previous); + match_equals(state, previous); xbt_dynar_free(&previous); } return 0; @@ -1255,14 +1250,14 @@ int compare_heap_area(void *area1, void* area2, xbt_dynar_t previous, xbt_dict_t if(size <= 0){ if(match_pairs){ - match_equals(previous); + match_equals(state, previous); xbt_dynar_free(&previous); } return 0; } - if((heapinfo1[block1].busy_frag.ignore[frag1] > 0) && ( heapinfo2[block2].busy_frag.ignore[frag2] == heapinfo1[block1].busy_frag.ignore[frag1])) - check_ignore = heapinfo1[block1].busy_frag.ignore[frag1]; + if((state->heapinfo1[block1].busy_frag.ignore[frag1] > 0) && ( state->heapinfo2[block2].busy_frag.ignore[frag2] == state->heapinfo1[block1].busy_frag.ignore[frag1])) + check_ignore = state->heapinfo1[block1].busy_frag.ignore[frag1]; }else{ @@ -1277,9 +1272,9 @@ int compare_heap_area(void *area1, void* area2, xbt_dynar_t previous, xbt_dict_t /* Start comparison*/ if(type_id != NULL){ if(switch_type) - res_compare = compare_heap_area_with_type(area1, area2, area1_to_compare, area2_to_compare, previous, other_types, all_types, type_id, size, check_ignore, pointer_level); + res_compare = compare_heap_area_with_type(state, area1, area2, area1_to_compare, area2_to_compare, previous, other_info, info, type_id, size, check_ignore, pointer_level); else - res_compare = compare_heap_area_with_type(area1, area2, area1_to_compare, area2_to_compare, previous, all_types, other_types, type_id, size, check_ignore, pointer_level); + res_compare = compare_heap_area_with_type(state, area1, area2, area1_to_compare, area2_to_compare, previous, info, other_info, type_id, size, check_ignore, pointer_level); if(res_compare == 1){ if(match_pairs) xbt_dynar_free(&previous); @@ -1287,9 +1282,9 @@ int compare_heap_area(void *area1, void* area2, xbt_dynar_t previous, xbt_dict_t } }else{ if(switch_type) - res_compare = compare_heap_area_without_type(area1, area2, area1_to_compare, area2_to_compare, previous, other_types, all_types, size, check_ignore); + res_compare = compare_heap_area_without_type(state, area1, area2, area1_to_compare, area2_to_compare, previous, other_info, info, size, check_ignore); else - res_compare = compare_heap_area_without_type(area1, area2, area1_to_compare, area2_to_compare, previous, all_types, other_types, size, check_ignore); + res_compare = compare_heap_area_without_type(state, area1, area2, area1_to_compare, area2_to_compare, previous, info, other_info, size, check_ignore); if(res_compare == 1){ if(match_pairs) xbt_dynar_free(&previous); @@ -1298,7 +1293,7 @@ int compare_heap_area(void *area1, void* area2, xbt_dynar_t previous, xbt_dict_t } if(match_pairs){ - match_equals(previous); + match_equals(state, previous); xbt_dynar_free(&previous); } @@ -1308,20 +1303,22 @@ int compare_heap_area(void *area1, void* area2, xbt_dynar_t previous, xbt_dict_t /*********************************************** Miscellaneous ***************************************************/ /****************************************************************************************************************/ +// Not used: +static int get_pointed_area_size(void *area, int heap){ -int get_pointed_area_size(void *area, int heap){ + struct s_mm_diff *state = mm_diff_info; int block, frag; malloc_info *heapinfo; if(heap == 1) - heapinfo = heapinfo1; + heapinfo = state->heapinfo1; else - heapinfo = heapinfo2; + heapinfo = state->heapinfo2; - block = ((char*)area - (char*)((xbt_mheap_t)s_heap)->heapbase) / BLOCKSIZE + 1; + block = ((char*)area - (char*)((xbt_mheap_t)state->s_heap)->heapbase) / BLOCKSIZE + 1; - if(((char *)area < (char*)((xbt_mheap_t)s_heap)->heapbase) || (block > heapsize1) || (block < 1)) + if(((char *)area < (char*)((xbt_mheap_t)state->s_heap)->heapbase) || (block > state->heapsize1) || (block < 1)) return -1; if(heapinfo[block].type == -1){ /* Free block */ @@ -1335,14 +1332,15 @@ int get_pointed_area_size(void *area, int heap){ } -char *get_type_description(xbt_dict_t types, char *type_name){ +// Not used: +char *get_type_description(mc_object_info_t info, char *type_name){ xbt_dict_cursor_t dict_cursor; char *type_origin; dw_type_t type; - xbt_dict_foreach(types, dict_cursor, type_origin, type){ - if(type->name && (strcmp(type->name, type_name) == 0) && type->size > 0){ + xbt_dict_foreach(info->types, dict_cursor, type_origin, type){ + if(type->name && (strcmp(type->name, type_name) == 0) && type->byte_size > 0){ xbt_dict_cursor_free(&dict_cursor); return type_origin; } @@ -1357,8 +1355,11 @@ char *get_type_description(xbt_dict_t types, char *type_name){ #define max( a, b ) ( ((a) > (b)) ? (a) : (b) ) #endif +// Not used: int mmalloc_linear_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2){ + struct s_mm_diff *state = mm_diff_info; + if(heap1 == NULL && heap1 == NULL){ XBT_DEBUG("Malloc descriptors null"); return 0; @@ -1370,18 +1371,18 @@ int mmalloc_linear_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2){ } /* Heap information */ - heaplimit = ((struct mdesc *)heap1)->heaplimit; + state->heaplimit = ((struct mdesc *)heap1)->heaplimit; - s_heap = (char *)mmalloc_get_current_heap() - STD_HEAP_SIZE - getpagesize(); + state->s_heap = (char *)mmalloc_get_current_heap() - STD_HEAP_SIZE - getpagesize(); - heapbase1 = (char *)heap1 + BLOCKSIZE; - heapbase2 = (char *)heap2 + BLOCKSIZE; + state->heapbase1 = (char *)heap1 + BLOCKSIZE; + state->heapbase2 = (char *)heap2 + BLOCKSIZE; - heapinfo1 = (malloc_info *)((char *)heap1 + ((uintptr_t)((char *)heap1->heapinfo - (char *)s_heap))); - heapinfo2 = (malloc_info *)((char *)heap2 + ((uintptr_t)((char *)heap2->heapinfo - (char *)s_heap))); + state->heapinfo1 = (malloc_info *)((char *)heap1 + ((uintptr_t)((char *)heap1->heapinfo - (char *)state->s_heap))); + state->heapinfo2 = (malloc_info *)((char *)heap2 + ((uintptr_t)((char *)heap2->heapinfo - (char *)state->s_heap))); - heapsize1 = heap1->heapsize; - heapsize2 = heap2->heapsize; + state->heapsize1 = heap1->heapsize; + state->heapsize2 = heap2->heapsize; /* Start comparison */ size_t i, j, k; @@ -1393,30 +1394,30 @@ int mmalloc_linear_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2){ i = 1; - while(i <= heaplimit){ + while(i <= state->heaplimit){ - addr_block1 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase1)); - addr_block2 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase2)); + addr_block1 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)state->heapbase1)); + addr_block2 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)state->heapbase2)); - if(heapinfo1[i].type != heapinfo2[i].type){ + if(state->heapinfo1[i].type != state->heapinfo2[i].type){ distance += BLOCKSIZE; - XBT_DEBUG("Different type of blocks (%zu) : %d - %d -> distance = %d", i, heapinfo1[i].type, heapinfo2[i].type, distance); + XBT_DEBUG("Different type of blocks (%zu) : %d - %d -> distance = %d", i, state->heapinfo1[i].type, state->heapinfo2[i].type, distance); i++; }else{ - if(heapinfo1[i].type == -1){ /* Free block */ + if(state->heapinfo1[i].type == -1){ /* Free block */ i++; continue; } - if(heapinfo1[i].type == 0){ /* Large block */ + if(state->heapinfo1[i].type == 0){ /* Large block */ - if(heapinfo1[i].busy_block.size != heapinfo2[i].busy_block.size){ - distance += BLOCKSIZE * max(heapinfo1[i].busy_block.size, heapinfo2[i].busy_block.size); - i += max(heapinfo1[i].busy_block.size, heapinfo2[i].busy_block.size); - XBT_DEBUG("Different larger of cluster at block %zu : %zu - %zu -> distance = %d", i, heapinfo1[i].busy_block.size, heapinfo2[i].busy_block.size, distance); + if(state->heapinfo1[i].busy_block.size != state->heapinfo2[i].busy_block.size){ + distance += BLOCKSIZE * max(state->heapinfo1[i].busy_block.size, state->heapinfo2[i].busy_block.size); + i += max(state->heapinfo1[i].busy_block.size, state->heapinfo2[i].busy_block.size); + XBT_DEBUG("Different larger of cluster at block %zu : %zu - %zu -> distance = %d", i, state->heapinfo1[i].busy_block.size, state->heapinfo2[i].busy_block.size, distance); continue; } @@ -1430,7 +1431,7 @@ int mmalloc_linear_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2){ k = 0; //while(k < (heapinfo1[i].busy_block.busy_size)){ - while(k < heapinfo1[i].busy_block.size * BLOCKSIZE){ + while(k < state->heapinfo1[i].busy_block.size * BLOCKSIZE){ if(memcmp((char *)addr_block1 + k, (char *)addr_block2 + k, 1) != 0){ distance ++; } @@ -1441,12 +1442,12 @@ int mmalloc_linear_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2){ }else { /* Fragmented block */ - for(j=0; j < (size_t) (BLOCKSIZE >> heapinfo1[i].type); j++){ + for(j=0; j < (size_t) (BLOCKSIZE >> state->heapinfo1[i].type); j++){ - addr_frag1 = (void*) ((char *)addr_block1 + (j << heapinfo1[i].type)); - addr_frag2 = (void*) ((char *)addr_block2 + (j << heapinfo2[i].type)); + addr_frag1 = (void*) ((char *)addr_block1 + (j << state->heapinfo1[i].type)); + addr_frag2 = (void*) ((char *)addr_block2 + (j << state->heapinfo2[i].type)); - if(heapinfo1[i].busy_frag.frag_size[j] == 0 && heapinfo2[i].busy_frag.frag_size[j] == 0){ + if(state->heapinfo1[i].busy_frag.frag_size[j] == 0 && state->heapinfo2[i].busy_frag.frag_size[j] == 0){ continue; } @@ -1460,7 +1461,7 @@ int mmalloc_linear_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2){ k=0; //while(k < max(heapinfo1[i].busy_frag.frag_size[j], heapinfo2[i].busy_frag.frag_size[j])){ - while(k < (BLOCKSIZE / (BLOCKSIZE >> heapinfo1[i].type))){ + while(k < (BLOCKSIZE / (BLOCKSIZE >> state->heapinfo1[i].type))){ if(memcmp((char *)addr_frag1 + k, (char *)addr_frag2 + k, 1) != 0){ distance ++; } diff --git a/teshsuite/smpi/mpich3-test/coll/bcastzerotype.c b/teshsuite/smpi/mpich3-test/coll/bcastzerotype.c index ece1e2549d..9ebf1f7fde 100644 --- a/teshsuite/smpi/mpich3-test/coll/bcastzerotype.c +++ b/teshsuite/smpi/mpich3-test/coll/bcastzerotype.c @@ -20,7 +20,7 @@ int main(int argc, char *argv[]) /* a random non-zero sized buffer */ #define NELEM (10) buf = malloc(NELEM*sizeof(int)); - assert(buf); + assert(buf!=NULL); for (i = 0; i < NELEM; i++) { buf[i] = wrank * NELEM + i; diff --git a/teshsuite/smpi/mpich3-test/datatype/unusual-noncontigs.c b/teshsuite/smpi/mpich3-test/datatype/unusual-noncontigs.c index d6fd63cf1e..58442071b3 100644 --- a/teshsuite/smpi/mpich3-test/datatype/unusual-noncontigs.c +++ b/teshsuite/smpi/mpich3-test/datatype/unusual-noncontigs.c @@ -534,7 +534,7 @@ static int pack_and_check_expected(MPI_Datatype type, const char *name, err = MPI_Pack_size(type_size/sizeof(int), MPI_INT, MPI_COMM_SELF, &pack_size); check_err(MPI_Pack_size); pack_buf = malloc(pack_size); - assert(pack_buf); + assert(pack_buf!=NULL); pos = 0; err = MPI_Pack(&sendbuf[0], type_size/sizeof(int), MPI_INT, pack_buf, pack_size, &pos, MPI_COMM_SELF);