Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of git+ssh://scm.gforge.inria.fr//gitroot/simgrid/simgrid
authorPierre Veyre <pierre.veyre@cc.in2p3.fr>
Fri, 21 Mar 2014 15:24:51 +0000 (16:24 +0100)
committerPierre Veyre <pierre.veyre@cc.in2p3.fr>
Fri, 21 Mar 2014 15:24:51 +0000 (16:24 +0100)
49 files changed:
CMakeLists.txt
buildtools/Cmake/AddTests.cmake
buildtools/Cmake/CompleteInFiles.cmake
buildtools/Cmake/DefinePackages.cmake
buildtools/Cmake/MakeExe.cmake
buildtools/Cmake/MakeLib.cmake
buildtools/Cmake/Modules/FindLibdw.cmake [new file with mode: 0644]
buildtools/Cmake/Modules/FindLibunwind.cmake
examples/msg/mc/bugged1.tesh
examples/msg/mc/bugged1_liveness.tesh
examples/msg/mc/bugged1_liveness_visited.tesh
examples/msg/mc/bugged2.tesh
examples/smpi/CMakeLists.txt
examples/smpi/mc/hostfile_non_deterministic [new file with mode: 0644]
examples/smpi/mc/hostfile_send_deterministic [new file with mode: 0644]
examples/smpi/mc/non_deterministic.c [new file with mode: 0644]
examples/smpi/mc/send_deterministic.c [new file with mode: 0644]
generate.sh [new file with mode: 0755]
include/smpi/mpi.h
include/xbt/mmalloc.h
src/include/mc/datatypes.h
src/include/mc/mc.h
src/mc/mc_checkpoint.c
src/mc/mc_compare.c
src/mc/mc_dpor.c
src/mc/mc_dwarf.c [new file with mode: 0644]
src/mc/mc_dwarf_attrnames.h [new file with mode: 0644]
src/mc/mc_dwarf_expression.c [new file with mode: 0644]
src/mc/mc_dwarf_tagnames.h [new file with mode: 0644]
src/mc/mc_global.c
src/mc/mc_hash.c [new file with mode: 0644]
src/mc/mc_liveness.c
src/mc/mc_member.c [new file with mode: 0644]
src/mc/mc_memory.c
src/mc/mc_private.h
src/mc/mc_request.c
src/mc/mc_set.cpp [new file with mode: 0644]
src/mc/mc_state.c
src/simgrid/sg_config.c
src/simix/smx_network.c
src/smpi/smpi_base.c
src/smpi/smpi_global.c
src/xbt/backtrace_linux.c
src/xbt/mmalloc/mm_diff.c
teshsuite/smpi/mpich3-test/coll/bcastzerotype.c
teshsuite/smpi/mpich3-test/datatype/unusual-noncontigs.c
testsuite/mc/CMakeLists.txt [new file with mode: 0644]
testsuite/mc/dwarf.c [new file with mode: 0644]
testsuite/mc/dwarf_expression.c [new file with mode: 0644]

index 621f9f6..8ea7ddf 100644 (file)
@@ -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()
 
index 0accf2c..f9b62f9 100644 (file)
@@ -704,6 +704,11 @@ add_test(test-surf-usage                        ${CMAKE_BINARY_DIR}/testsuite/su
 add_test(test-surf-usage2                       ${CMAKE_BINARY_DIR}/testsuite/surf/surf_usage2 --cfg=path:${CMAKE_HOME_DIRECTORY}/testsuite/surf/ platform.xml)
 add_test(test-surf-trace                        ${CMAKE_BINARY_DIR}/testsuite/surf/trace_usage --cfg=path:${CMAKE_HOME_DIRECTORY}/testsuite/surf/)
 
+if(HAVE_MC)
+  add_test(mc-dwarf                             ${CMAKE_BINARY_DIR}/testsuite/mc/dwarf)
+  add_test(mc-dwarf-expression                  ${CMAKE_BINARY_DIR}/testsuite/mc/dwarf-expression)
+endif()
+
 add_test(testall                                ${CMAKE_BINARY_DIR}/src/testall)
 
 if(enable_auto_install)
index 5db8766..1e21249 100644 (file)
@@ -230,6 +230,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")
index a414011..3b5ee1a 100644 (file)
@@ -568,6 +568,9 @@ set(MC_SRC
   src/mc/mc_compare.c
   src/mc/mc_dpor.c
   src/mc/mc_global.c
+  src/mc/mc_dwarf
+  src/mc/mc_member.c
+  src/mc/mc_dwarf_expression.c
   src/mc/mc_liveness.c
   src/mc/mc_memory.c
   src/mc/mc_private.h
@@ -575,6 +578,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
@@ -1011,6 +1016,7 @@ set(TOOLS_CMAKEFILES_TXT
 set(TESTSUITE_CMAKEFILES_TXT
   testsuite/surf/CMakeLists.txt
   testsuite/xbt/CMakeLists.txt
+  testsuite/mc/CMakeLists.txt
   )
 
 set(CMAKE_SOURCE_FILES
@@ -1035,6 +1041,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
index 1742b95..299103e 100644 (file)
@@ -118,6 +118,7 @@ add_subdirectory(${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/mpich3-test/f90/pt2pt)
 
 add_subdirectory(${CMAKE_HOME_DIRECTORY}/teshsuite/xbt)
 
+add_subdirectory(${CMAKE_HOME_DIRECTORY}/testsuite/mc)
 add_subdirectory(${CMAKE_HOME_DIRECTORY}/testsuite/surf)
 add_subdirectory(${CMAKE_HOME_DIRECTORY}/testsuite/xbt)
 
index bbf9eab..ef15efa 100644 (file)
@@ -86,6 +86,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 (file)
index 0000000..9e07a38
--- /dev/null
@@ -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)
index 56de1f7..03bbed9 100644 (file)
@@ -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)
index 464633f..504b90e 100644 (file)
@@ -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
@@ -22,16 +24,16 @@ $ ${bindir:=.}/bugged1 --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%
 > [  0.000000] (1:server@HostA) *** PROPERTY NOT VALID ***
 > [  0.000000] (1:server@HostA) **************************
 > [  0.000000] (1:server@HostA) Counter-example execution trace:
-> [  0.000000] (1:server@HostA) [(1)HostA (server)] iRecv(dst=(1)HostA (server), buff=(verbose only), size=(verbose only)) (56)
-> [  0.000000] (1:server@HostA) [(2)HostB (client)] iSend(src=(2)HostB (client), buff=(verbose only), size=(verbose only)) (54)
-> [  0.000000] (1:server@HostA) [(1)HostA (server)] Wait(comm=(verbose only) [(2)HostB (client)-> (1)HostA (server)]) (62)
-> [  0.000000] (1:server@HostA) [(1)HostA (server)] iRecv(dst=(1)HostA (server), buff=(verbose only), size=(verbose only)) (56)
-> [  0.000000] (1:server@HostA) [(2)HostB (client)] Wait(comm=(verbose only) [(2)HostB (client)-> (1)HostA (server)]) (62)
-> [  0.000000] (1:server@HostA) [(4)HostD (client)] iSend(src=(4)HostD (client), buff=(verbose only), size=(verbose only)) (54)
-> [  0.000000] (1:server@HostA) [(1)HostA (server)] Wait(comm=(verbose only) [(4)HostD (client)-> (1)HostA (server)]) (62)
-> [  0.000000] (1:server@HostA) [(1)HostA (server)] iRecv(dst=(1)HostA (server), buff=(verbose only), size=(verbose only)) (56)
-> [  0.000000] (1:server@HostA) [(3)HostC (client)] iSend(src=(3)HostC (client), buff=(verbose only), size=(verbose only)) (54)
-> [  0.000000] (1:server@HostA) [(1)HostA (server)] Wait(comm=(verbose only) [(3)HostC (client)-> (1)HostA (server)]) (62)
+> [  0.000000] (1:server@HostA) [(1)HostA (server)] iRecv(dst=(1)HostA (server), buff=(verbose only), size=(verbose only))
+> [  0.000000] (1:server@HostA) [(2)HostB (client)] iSend(src=(2)HostB (client), buff=(verbose only), size=(verbose only))
+> [  0.000000] (1:server@HostA) [(1)HostA (server)] Wait(comm=(verbose only) [(2)HostB (client)-> (1)HostA (server)])
+> [  0.000000] (1:server@HostA) [(1)HostA (server)] iRecv(dst=(1)HostA (server), buff=(verbose only), size=(verbose only))
+> [  0.000000] (1:server@HostA) [(2)HostB (client)] Wait(comm=(verbose only) [(2)HostB (client)-> (1)HostA (server)])
+> [  0.000000] (1:server@HostA) [(4)HostD (client)] iSend(src=(4)HostD (client), buff=(verbose only), size=(verbose only))
+> [  0.000000] (1:server@HostA) [(1)HostA (server)] Wait(comm=(verbose only) [(4)HostD (client)-> (1)HostA (server)])
+> [  0.000000] (1:server@HostA) [(1)HostA (server)] iRecv(dst=(1)HostA (server), buff=(verbose only), size=(verbose only))
+> [  0.000000] (1:server@HostA) [(3)HostC (client)] iSend(src=(3)HostC (client), buff=(verbose only), size=(verbose only))
+> [  0.000000] (1:server@HostA) [(1)HostA (server)] Wait(comm=(verbose only) [(3)HostC (client)-> (1)HostA (server)])
 > [  0.000000] (1:server@HostA) Expanded states = 22
 > [  0.000000] (1:server@HostA) Visited states = 56
 > [  0.000000] (1:server@HostA) Executed transitions = 52
index 37652b8..fd34555 100644 (file)
@@ -20,26 +20,26 @@ $ ${bindir:=.}/bugged1_liveness ${srcdir:=.}/../msg_platform.xml ${srcdir:=.}/de
 > [  0.000000] (0:@) |             ACCEPTANCE CYCLE            |
 > [  0.000000] (0:@) *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
 > [  0.000000] (0:@) Counter-example that violates formula :
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only)) (56)
-> [  0.000000] (0:@) [(2)Boivin (client)] iSend(src=(2)Boivin (client), buff=(verbose only), size=(verbose only)) (54)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)]) (62)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only)) (56)
-> [  0.000000] (0:@) [(2)Boivin (client)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)]) (62)
-> [  0.000000] (0:@) [(2)Boivin (client)] iRecv(dst=(2)Boivin (client), buff=(verbose only), size=(verbose only)) (56)
-> [  0.000000] (0:@) [(3)Fafard (client)] iSend(src=(3)Fafard (client), buff=(verbose only), size=(verbose only)) (54)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(3)Fafard (client)-> (1)Tremblay (coordinator)]) (62)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iSend(src=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only)) (54)
-> [  0.000000] (0:@) [(3)Fafard (client)] Wait(comm=(verbose only) [(3)Fafard (client)-> (1)Tremblay (coordinator)]) (62)
-> [  0.000000] (0:@) [(3)Fafard (client)] iRecv(dst=(3)Fafard (client), buff=(verbose only), size=(verbose only)) (56)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(1)Tremblay (coordinator)-> (3)Fafard (client)]) (62)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only)) (56)
-> [  0.000000] (0:@) [(3)Fafard (client)] Wait(comm=(verbose only) [(1)Tremblay (coordinator)-> (3)Fafard (client)]) (62)
-> [  0.000000] (0:@) [(3)Fafard (client)] iSend(src=(3)Fafard (client), buff=(verbose only), size=(verbose only)) (54)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(3)Fafard (client)-> (1)Tremblay (coordinator)]) (62)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only)) (56)
-> [  0.000000] (0:@) [(3)Fafard (client)] Wait(comm=(verbose only) [(3)Fafard (client)-> (1)Tremblay (coordinator)]) (62)
-> [  0.000000] (0:@) [(3)Fafard (client)] iSend(src=(3)Fafard (client), buff=(verbose only), size=(verbose only)) (54)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(3)Fafard (client)-> (1)Tremblay (coordinator)]) (62)
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(2)Boivin (client)] iSend(src=(2)Boivin (client), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)])
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(2)Boivin (client)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)])
+> [  0.000000] (0:@) [(2)Boivin (client)] iRecv(dst=(2)Boivin (client), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(3)Fafard (client)] iSend(src=(3)Fafard (client), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(3)Fafard (client)-> (1)Tremblay (coordinator)])
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iSend(src=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(3)Fafard (client)] Wait(comm=(verbose only) [(3)Fafard (client)-> (1)Tremblay (coordinator)])
+> [  0.000000] (0:@) [(3)Fafard (client)] iRecv(dst=(3)Fafard (client), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(1)Tremblay (coordinator)-> (3)Fafard (client)])
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(3)Fafard (client)] Wait(comm=(verbose only) [(1)Tremblay (coordinator)-> (3)Fafard (client)])
+> [  0.000000] (0:@) [(3)Fafard (client)] iSend(src=(3)Fafard (client), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(3)Fafard (client)-> (1)Tremblay (coordinator)])
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(3)Fafard (client)] Wait(comm=(verbose only) [(3)Fafard (client)-> (1)Tremblay (coordinator)])
+> [  0.000000] (0:@) [(3)Fafard (client)] iSend(src=(3)Fafard (client), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(3)Fafard (client)-> (1)Tremblay (coordinator)])
 > [  0.000000] (0:@) Expanded pairs = 21
 > [  0.000000] (0:@) Visited pairs = 21
 > [  0.000000] (0:@) Executed transitions = 20
index f8042cb..f117bb4 100644 (file)
@@ -78,56 +78,56 @@ $ ${bindir:=.}/bugged1_liveness ${srcdir:=.}/../msg_platform.xml ${srcdir:=.}/de
 > [  0.000000] (0:@) |             ACCEPTANCE CYCLE            |
 > [  0.000000] (0:@) *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
 > [  0.000000] (0:@) Counter-example that violates formula :
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only)) (56)
-> [  0.000000] (0:@) [(2)Boivin (client)] iSend(src=(2)Boivin (client), buff=(verbose only), size=(verbose only)) (54)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)]) (62)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iSend(src=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only)) (54)
-> [  0.000000] (0:@) [(2)Boivin (client)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)]) (62)
-> [  0.000000] (0:@) [(2)Boivin (client)] iRecv(dst=(2)Boivin (client), buff=(verbose only), size=(verbose only)) (56)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(1)Tremblay (coordinator)-> (2)Boivin (client)]) (62)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only)) (56)
-> [  0.000000] (0:@) [(2)Boivin (client)] Wait(comm=(verbose only) [(1)Tremblay (coordinator)-> (2)Boivin (client)]) (62)
-> [  0.000000] (0:@) [(2)Boivin (client)] iSend(src=(2)Boivin (client), buff=(verbose only), size=(verbose only)) (54)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)]) (62)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only)) (56)
-> [  0.000000] (0:@) [(2)Boivin (client)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)]) (62)
-> [  0.000000] (0:@) [(2)Boivin (client)] iSend(src=(2)Boivin (client), buff=(verbose only), size=(verbose only)) (54)
-> [  0.000000] (0:@) [(2)Boivin (client)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)]) (62)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)]) (62)
-> [  0.000000] (0:@) [(2)Boivin (client)] iRecv(dst=(2)Boivin (client), buff=(verbose only), size=(verbose only)) (56)
-> [  0.000000] (0:@) [(3)Fafard (client)] iSend(src=(3)Fafard (client), buff=(verbose only), size=(verbose only)) (54)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iSend(src=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only)) (54)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(1)Tremblay (coordinator)-> (2)Boivin (client)]) (62)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only)) (56)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(3)Fafard (client)-> (1)Tremblay (coordinator)]) (62)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only)) (56)
-> [  0.000000] (0:@) [(2)Boivin (client)] Wait(comm=(verbose only) [(1)Tremblay (coordinator)-> (2)Boivin (client)]) (62)
-> [  0.000000] (0:@) [(2)Boivin (client)] iSend(src=(2)Boivin (client), buff=(verbose only), size=(verbose only)) (54)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)]) (62)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only)) (56)
-> [  0.000000] (0:@) [(2)Boivin (client)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)]) (62)
-> [  0.000000] (0:@) [(2)Boivin (client)] iSend(src=(2)Boivin (client), buff=(verbose only), size=(verbose only)) (54)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)]) (62)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iSend(src=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only)) (54)
-> [  0.000000] (0:@) [(2)Boivin (client)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)]) (62)
-> [  0.000000] (0:@) [(2)Boivin (client)] iRecv(dst=(2)Boivin (client), buff=(verbose only), size=(verbose only)) (56)
-> [  0.000000] (0:@) [(2)Boivin (client)] Wait(comm=(verbose only) [(1)Tremblay (coordinator)-> (2)Boivin (client)]) (62)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(1)Tremblay (coordinator)-> (2)Boivin (client)]) (62)
-> [  0.000000] (0:@) [(2)Boivin (client)] iSend(src=(2)Boivin (client), buff=(verbose only), size=(verbose only)) (54)
-> [  0.000000] (0:@) [(3)Fafard (client)] Wait(comm=(verbose only) [(3)Fafard (client)-> (1)Tremblay (coordinator)]) (62)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only)) (56)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)]) (62)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only)) (56)
-> [  0.000000] (0:@) [(2)Boivin (client)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)]) (62)
-> [  0.000000] (0:@) [(2)Boivin (client)] iSend(src=(2)Boivin (client), buff=(verbose only), size=(verbose only)) (54)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)]) (62)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iSend(src=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only)) (54)
-> [  0.000000] (0:@) [(2)Boivin (client)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)]) (62)
-> [  0.000000] (0:@) [(2)Boivin (client)] iRecv(dst=(2)Boivin (client), buff=(verbose only), size=(verbose only)) (56)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(1)Tremblay (coordinator)-> (2)Boivin (client)]) (62)
-> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only)) (56)
-> [  0.000000] (0:@) [(2)Boivin (client)] Wait(comm=(verbose only) [(1)Tremblay (coordinator)-> (2)Boivin (client)]) (62)
-> [  0.000000] (0:@) [(2)Boivin (client)] iSend(src=(2)Boivin (client), buff=(verbose only), size=(verbose only)) (54)
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(2)Boivin (client)] iSend(src=(2)Boivin (client), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)])
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iSend(src=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(2)Boivin (client)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)])
+> [  0.000000] (0:@) [(2)Boivin (client)] iRecv(dst=(2)Boivin (client), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(1)Tremblay (coordinator)-> (2)Boivin (client)])
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(2)Boivin (client)] Wait(comm=(verbose only) [(1)Tremblay (coordinator)-> (2)Boivin (client)])
+> [  0.000000] (0:@) [(2)Boivin (client)] iSend(src=(2)Boivin (client), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)])
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(2)Boivin (client)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)])
+> [  0.000000] (0:@) [(2)Boivin (client)] iSend(src=(2)Boivin (client), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(2)Boivin (client)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)])
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)])
+> [  0.000000] (0:@) [(2)Boivin (client)] iRecv(dst=(2)Boivin (client), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(3)Fafard (client)] iSend(src=(3)Fafard (client), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iSend(src=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(1)Tremblay (coordinator)-> (2)Boivin (client)])
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(3)Fafard (client)-> (1)Tremblay (coordinator)])
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(2)Boivin (client)] Wait(comm=(verbose only) [(1)Tremblay (coordinator)-> (2)Boivin (client)])
+> [  0.000000] (0:@) [(2)Boivin (client)] iSend(src=(2)Boivin (client), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)])
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(2)Boivin (client)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)])
+> [  0.000000] (0:@) [(2)Boivin (client)] iSend(src=(2)Boivin (client), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)])
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iSend(src=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(2)Boivin (client)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)])
+> [  0.000000] (0:@) [(2)Boivin (client)] iRecv(dst=(2)Boivin (client), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(2)Boivin (client)] Wait(comm=(verbose only) [(1)Tremblay (coordinator)-> (2)Boivin (client)])
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(1)Tremblay (coordinator)-> (2)Boivin (client)])
+> [  0.000000] (0:@) [(2)Boivin (client)] iSend(src=(2)Boivin (client), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(3)Fafard (client)] Wait(comm=(verbose only) [(3)Fafard (client)-> (1)Tremblay (coordinator)])
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)])
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(2)Boivin (client)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)])
+> [  0.000000] (0:@) [(2)Boivin (client)] iSend(src=(2)Boivin (client), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)])
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iSend(src=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(2)Boivin (client)] Wait(comm=(verbose only) [(2)Boivin (client)-> (1)Tremblay (coordinator)])
+> [  0.000000] (0:@) [(2)Boivin (client)] iRecv(dst=(2)Boivin (client), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] Wait(comm=(verbose only) [(1)Tremblay (coordinator)-> (2)Boivin (client)])
+> [  0.000000] (0:@) [(1)Tremblay (coordinator)] iRecv(dst=(1)Tremblay (coordinator), buff=(verbose only), size=(verbose only))
+> [  0.000000] (0:@) [(2)Boivin (client)] Wait(comm=(verbose only) [(1)Tremblay (coordinator)-> (2)Boivin (client)])
+> [  0.000000] (0:@) [(2)Boivin (client)] iSend(src=(2)Boivin (client), buff=(verbose only), size=(verbose only))
 > [  0.000000] (0:@) Expanded pairs = 57
 > [  0.000000] (0:@) Visited pairs = 208
 > [  0.000000] (0:@) Executed transitions = 207
index 2fe18e9..3d65e67 100644 (file)
@@ -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
@@ -887,13 +889,13 @@ $ ${bindir:=.}/bugged2 --cfg=model-check:1 "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%
 > [  0.000000] (1:server@HostA) *** PROPERTY NOT VALID ***
 > [  0.000000] (1:server@HostA) **************************
 > [  0.000000] (1:server@HostA) Counter-example execution trace:
-> [  0.000000] (1:server@HostA) [(1)HostA (server)] iRecv(dst=(1)HostA (server), buff=(verbose only), size=(verbose only)) (56)
-> [  0.000000] (1:server@HostA) [(3)HostC (client)] iSend(src=(3)HostC (client), buff=(verbose only), size=(verbose only)) (54)
-> [  0.000000] (1:server@HostA) [(1)HostA (server)] Wait(comm=(verbose only) [(3)HostC (client)-> (1)HostA (server)]) (62)
-> [  0.000000] (1:server@HostA) [(3)HostC (client)] Wait(comm=(verbose only) [(3)HostC (client)-> (1)HostA (server)]) (62)
-> [  0.000000] (1:server@HostA) [(1)HostA (server)] iRecv(dst=(1)HostA (server), buff=(verbose only), size=(verbose only)) (56)
-> [  0.000000] (1:server@HostA) [(3)HostC (client)] iSend(src=(3)HostC (client), buff=(verbose only), size=(verbose only)) (54)
-> [  0.000000] (1:server@HostA) [(1)HostA (server)] Wait(comm=(verbose only) [(3)HostC (client)-> (1)HostA (server)]) (62)
+> [  0.000000] (1:server@HostA) [(1)HostA (server)] iRecv(dst=(1)HostA (server), buff=(verbose only), size=(verbose only))
+> [  0.000000] (1:server@HostA) [(3)HostC (client)] iSend(src=(3)HostC (client), buff=(verbose only), size=(verbose only))
+> [  0.000000] (1:server@HostA) [(1)HostA (server)] Wait(comm=(verbose only) [(3)HostC (client)-> (1)HostA (server)])
+> [  0.000000] (1:server@HostA) [(3)HostC (client)] Wait(comm=(verbose only) [(3)HostC (client)-> (1)HostA (server)])
+> [  0.000000] (1:server@HostA) [(1)HostA (server)] iRecv(dst=(1)HostA (server), buff=(verbose only), size=(verbose only))
+> [  0.000000] (1:server@HostA) [(3)HostC (client)] iSend(src=(3)HostC (client), buff=(verbose only), size=(verbose only))
+> [  0.000000] (1:server@HostA) [(1)HostA (server)] Wait(comm=(verbose only) [(3)HostC (client)-> (1)HostA (server)])
 > [  0.000000] (1:server@HostA) Expanded states = 461
 > [  0.000000] (1:server@HostA) Visited states = 2271
 > [  0.000000] (1:server@HostA) Executed transitions = 2117
index 154b3d5..9afad64 100644 (file)
@@ -23,10 +23,14 @@ if(enable_smpi)
     add_executable(mc/bugged1 mc/bugged1.c)
     add_executable(mc/bugged2 mc/bugged2.c)
     add_executable(mc/bugged1_liveness mc/bugged1_liveness.c)
+    add_executable(mc/send_deterministic mc/send_deterministic.c)
+    add_executable(mc/non_deterministic mc/non_deterministic.c)
   
     target_link_libraries(mc/bugged1 simgrid)
     target_link_libraries(mc/bugged2 simgrid)
     target_link_libraries(mc/bugged1_liveness simgrid)
+    target_link_libraries(mc/send_deterministic simgrid)
+    target_link_libraries(mc/non_deterministic simgrid)
   endif()
   
   target_link_libraries(bcbench simgrid)
@@ -58,6 +62,8 @@ set(examples_src
   ${CMAKE_CURRENT_SOURCE_DIR}/mc/bugged2.c
   ${CMAKE_CURRENT_SOURCE_DIR}/mc/bugged1.c
   ${CMAKE_CURRENT_SOURCE_DIR}/mc/bugged1_liveness.c
+  ${CMAKE_CURRENT_SOURCE_DIR}/mc/send_deterministic.c
+  ${CMAKE_CURRENT_SOURCE_DIR}/mc/non_deterministic.c
   PARENT_SCOPE
   )
 set(bin_files
@@ -67,6 +73,8 @@ set(bin_files
   ${CMAKE_CURRENT_SOURCE_DIR}/mc/hostfile_bugged1_liveness
   ${CMAKE_CURRENT_SOURCE_DIR}/mc/hostfile_bugged1
   ${CMAKE_CURRENT_SOURCE_DIR}/mc/hostfile_bugged2
+  ${CMAKE_CURRENT_SOURCE_DIR}/mc/hostfile_send_deterministic
+  ${CMAKE_CURRENT_SOURCE_DIR}/mc/hostfile_non_deterministic
   PARENT_SCOPE
   )
 set(txt_files
diff --git a/examples/smpi/mc/hostfile_non_deterministic b/examples/smpi/mc/hostfile_non_deterministic
new file mode 100644 (file)
index 0000000..b6d1c07
--- /dev/null
@@ -0,0 +1,3 @@
+c-1.me
+c-2.me
+c-3.me
diff --git a/examples/smpi/mc/hostfile_send_deterministic b/examples/smpi/mc/hostfile_send_deterministic
new file mode 100644 (file)
index 0000000..b6d1c07
--- /dev/null
@@ -0,0 +1,3 @@
+c-1.me
+c-2.me
+c-3.me
diff --git a/examples/smpi/mc/non_deterministic.c b/examples/smpi/mc/non_deterministic.c
new file mode 100644 (file)
index 0000000..b73cbd2
--- /dev/null
@@ -0,0 +1,54 @@
+/* ../../../smpi_script/bin/smpirun -hostfile hostfile_send_deterministic -platform ../../platforms/cluster.xml -np 3 --cfg=model-check:1 --cfg=smpi/send_is_detached_thres:0 gdb\ --args\ ./send_deterministic */
+
+/* Copyright (c) 2009 - 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 <stdio.h>
+#include <mpi.h>
+#include <simgrid/modelchecker.h>
+
+
+int main(int argc, char **argv)
+{
+  int recv_buff, err, size, rank, i;
+  MPI_Status status;
+
+  /* Initialize MPI */
+  err = MPI_Init(&argc, &argv);
+  if (err != MPI_SUCCESS) {
+    printf("MPI initialization failed!\n");
+    exit(1);
+  }
+
+  err = MPI_Comm_size(MPI_COMM_WORLD, &size);   /* Get nr of tasks */
+  err = MPI_Comm_rank(MPI_COMM_WORLD, &rank);   /* Get id of this process */
+  if (size < 2) {
+    printf("run this program with at least 2 processes \n");
+    MPI_Finalize();
+    exit(0);
+  }
+
+  if (rank == 0) {
+    printf("MPI_ISend / MPI_IRecv Test \n");
+
+    for(i=0; i < size - 1; i++){
+      MPI_Recv(&recv_buff, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
+      printf("Message received from %d\n", recv_buff);
+      MPI_Send(&recv_buff, 1, MPI_INT, status.MPI_SOURCE, 42, MPI_COMM_WORLD);
+      // printf("Sent %d to rank %d\n", status.MPI_SOURCE);
+    }
+
+  }else{
+    MPI_Send(&rank, 1, MPI_INT, 0, 42, MPI_COMM_WORLD);
+    printf("Sent %d to rank 0\n", rank);
+    MPI_Recv(&recv_buff, 1, MPI_INT, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
+    printf("Message received from %d\n", recv_buff);
+  }
+
+  MPI_Finalize();
+
+  return 0;
+}
diff --git a/examples/smpi/mc/send_deterministic.c b/examples/smpi/mc/send_deterministic.c
new file mode 100644 (file)
index 0000000..ecbcc49
--- /dev/null
@@ -0,0 +1,50 @@
+/* ../../../smpi_script/bin/smpirun -hostfile hostfile_send_deterministic -platform ../../platforms/cluster.xml -np 3 --cfg=model-check:1 --cfg=smpi/send_is_detached_thres:0 gdb\ --args\ ./send_deterministic */
+
+/* Copyright (c) 2009 - 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 <stdio.h>
+#include <mpi.h>
+#include <simgrid/modelchecker.h>
+
+
+int main(int argc, char **argv)
+{
+  int recv_buff, err, size, rank, i;
+  MPI_Status status;
+
+  /* Initialize MPI */
+  err = MPI_Init(&argc, &argv);
+  if (err != MPI_SUCCESS) {
+    printf("MPI initialization failed!\n");
+    exit(1);
+  }
+
+  err = MPI_Comm_size(MPI_COMM_WORLD, &size);   /* Get nr of tasks */
+  err = MPI_Comm_rank(MPI_COMM_WORLD, &rank);   /* Get id of this process */
+  if (size < 2) {
+    printf("run this program with at least 2 processes \n");
+    MPI_Finalize();
+    exit(0);
+  }
+
+  if (rank == 0) {
+    printf("MPI_ISend / MPI_IRecv Test \n");
+
+    for(i=0; i < size - 1; i++){
+      MPI_Recv(&recv_buff, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
+      printf("Message received from %d\n", recv_buff);
+    }
+
+  }else{
+    MPI_Send(&rank, 1, MPI_INT, 0, 42, MPI_COMM_WORLD);
+    printf("Sent %d to rank 0\n", rank);
+  }
+
+  MPI_Finalize();
+
+  return 0;
+}
diff --git a/generate.sh b/generate.sh
new file mode 100755 (executable)
index 0000000..5f39fdd
--- /dev/null
@@ -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
index 2830983..4224e7f 100644 (file)
 #include <xbt/sysdep.h>
 #include <xbt/log.h>
 #include <xbt/asserts.h>
+#include <simgrid/modelchecker.h>
+
+#ifdef HAVE_MC
+#undef assert
+#define assert(x) MC_assert(x)
+#endif
 
 #endif
index d583884..35c68e0 100644 (file)
@@ -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,13 @@ 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);
+struct s_mc_snapshot;
+
+int mmalloc_compare_heap(struct s_mc_snapshot* snapshot1, struct s_mc_snapshot* snapshot2, xbt_mheap_t heap1, xbt_mheap_t heap2);
 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, struct s_mc_snapshot* snapshot1, struct s_mc_snapshot* snapshot2, xbt_dynar_t previous, dw_type_t 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);
index 2cc5834..cd8caab 100644 (file)
@@ -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 <libunwind.h>
+#include <dwarf.h>
+
 SG_BEGIN_DECL()
 
 /******************************* Transitions **********************************/
@@ -37,34 +43,17 @@ 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{
-  e_dw_type_type type;
-  void *id;
-  char *name;
-  int size;
-  char *dw_type_id;
-  xbt_dynar_t members; /* if DW_TAG_structure_type */
-  int is_pointer_type;
-  int offset;
-}s_dw_type_t, *dw_type_t;
-
-char* get_type_description(xbt_dict_t types, char *type_name);
+typedef int e_dw_type_type;
+
+typedef struct s_dw_type s_dw_type_t, *dw_type_t;
+
+char* get_type_description(mc_object_info_t info, char *type_name);
 
 SG_END_DECL()
 #endif                          /* _MC_MC_H */
index 494b651..80f7146 100644 (file)
 #include "xbt/automaton.h"
 #include "xbt/dynar.h"
 
-#define STD_HEAP_SIZE   20480000        /* Maximum size of the system's heap */
+/* Maximum size of the application heap.
+ *
+ * The model-checker heap is placed at this offset from the
+ * beginning of the application heap.
+ *
+ * In the current implementation, if the application uses more
+ * than this for the application heap the application heap will
+ * smash the beginning of the model-checker heap and bad things
+ * will happen.
+ *
+ * For 64 bits systems, we have a lot of virtual memory available
+ * so we wan use a much bigger value in order to avoid bad things
+ * from happening.
+ * */
+
+#define STD_HEAP_SIZE   (sizeof(void*)<=4 ? (100*1024*1024) : (1ll*1024*1024*1024*1024))
 
 SG_BEGIN_DECL()
 
@@ -26,9 +41,12 @@ 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 int _sg_mc_send_determinism;
 
 extern xbt_dynar_t mc_heap_comparison_ignore;
 extern xbt_dynar_t stacks_areas;
@@ -40,9 +58,12 @@ 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);
+void _mc_cfg_cb_send_determinism(const char *name, int pos);
 
 XBT_PUBLIC(void) MC_do_the_modelcheck_for_real(void);
 
index 39e743a..d80a004 100644 (file)
@@ -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 <libgen.h>
+#define _GNU_SOURCE
+#define UNW_LOCAL_ONLY
+
+#include <string.h>
+#include <link.h>
 #include "mc_private.h"
 #include "xbt/module.h"
+#include <xbt/mmalloc.h>
+
+#include "xbt/mmalloc/mmprivate.h"
 
 #include "../simix/smx_private.h"
 
 #include <libunwind.h>
+#include <libelf.h>
+
+#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,243 @@ 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(){
+  xbt_assert(maestro_stack_start, "maestro_stack_start");
+  xbt_assert(maestro_stack_end, "maestro_stack_end");
+  xbt_assert(libsimgrid_path, "libsimgrid_path&");
 
-  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, 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->full_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, " ");
+  // TODO, support "switch type" (looking up the type in another lib) when possible
+}
 
-    if(lfields[0] == NULL)
-      continue;
+void MC_post_process_types(mc_object_info_t info) {
+  xbt_dict_cursor_t cursor = NULL;
+  char *origin;
+  dw_type_t type;
 
-    if(strcmp(lfields[0], "Sections:") == 0 || strcmp(lfields[0], "Idx") == 0 || strncmp(lfields[0], libsimgrid_path, strlen(libsimgrid_path)) == 0)
-      continue;
+  // Lookup "subtype" field:
+  xbt_dict_foreach(info->types, cursor, origin, type){
+    MC_resolve_subtype(info, type);
 
-    for (i = 1; i < 7 && lfields[i - 1] != NULL; i++) {
-      lfields[i] = strtok(NULL, " ");
+    dw_type_t member;
+    unsigned int i = 0;
+    if(type->members!=NULL) xbt_dynar_foreach(type->members, i, member) {
+      MC_resolve_subtype(info, member);
     }
-
-    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++;
-       }
-
-    }
-    
   }
-
-  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;
-
-  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, " ");
+/** \brief Fills the position of the .bss and .data sections. */
+void MC_find_object_address(memory_map_t maps, mc_object_info_t result) {
 
-    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 bool mc_valid_variable(dw_variable_t var, dw_frame_t frame, const void* ip) {
+  // The variable is not yet valid:
+  if((const void*)((const char*) frame->low_pc + var->start_scope) > ip)
+    return false;
+  else
+    return true;
 }
 
-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);
-
-    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);
+  xbt_dynar_foreach(stack_frames,cursor1,stack_frame) {
 
-    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)
+      if(!mc_valid_variable(current_variable, stack_frame->frame, (void*) stack_frame->ip))
+        continue;
+
+      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->locations.size != 0){
+        new_var->address = (void*) mc_dwarf_resolve_locations(&current_variable->locations,
+          &(stack_frame->unw_cursor), (void*)stack_frame->frame_base, NULL);
       }
 
       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;
+
   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;
 
-  ret = unw_init_local(&c, (unw_context_t *)stack_context);
-  if(ret < 0){
+    unw_word_t ip, sp;
+
+    unw_get_reg(&c, UNW_REG_IP, &ip);
+    unw_get_reg(&c, UNW_REG_SP, &sp);
+
+    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(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 +351,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 +425,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)
@@ -756,6 +450,47 @@ void MC_restore_snapshot(mc_snapshot_t snapshot){
 
 }
 
+void* mc_translate_address(uintptr_t addr, mc_snapshot_t snapshot) {
+
+  // If not in a process state/clone:
+  if(!snapshot) {
+    return (uintptr_t*) addr;
+  }
+
+  // If it is in a snapshot:
+  for(size_t i=0; i!=NB_REGIONS; ++i) {
+    mc_mem_region_t region = snapshot->regions[i];
+    uintptr_t start = (uintptr_t) region->start_addr;
+    uintptr_t end = start + region->size;
+
+    // The address is in this region:
+    if(addr >= start && addr < end) {
+      uintptr_t offset = addr - start;
+      return (void*) ((uintptr_t)region->data + offset);
+    }
+
+  }
+
+  // It is not in a snapshot:
+  return (void*) addr;
+}
+
+uintptr_t mc_untranslate_address(void* addr, mc_snapshot_t snapshot) {
+  if(!snapshot) {
+    return (uintptr_t) addr;
+  }
+
+  for(size_t i=0; i!=NB_REGIONS; ++i) {
+    mc_mem_region_t region = snapshot->regions[i];
+    if(addr>=region->data && addr<=(void*)(((char*)region->data)+region->size)) {
+      size_t offset = (size_t) ((char*) addr - (char*) region->data);
+      return ((uintptr_t) region->start_addr) + offset;
+    }
+  }
+
+  return (uintptr_t) addr;
+}
+
 mc_snapshot_t SIMIX_pre_mc_snapshot(smx_simcall_t simcall){
   return MC_take_snapshot(1);
 }
index e017b7d..8e51c81 100644 (file)
@@ -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 <inttypes.h>
+
 #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,138 +66,157 @@ 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_snapshot_t snapshot1, mc_snapshot_t snapshot2, 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;
+  int elm_size, i, res;
   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);
-    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_unspecified_type:
+    return 1;
+
+  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_const_type: /* Const variable cannot be modified */
-    return -1;
+  case DW_TAG_typedef:
+  case DW_TAG_volatile_type:
+  case DW_TAG_const_type:
+    return compare_areas_with_type(area1, area2, snapshot1, snapshot2, type->subtype, region_size, region_type, start_data, pointer_level);
     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));
-          switch_types = 1;
-        }
-      }
-      elm_size = subtype->size;
+    case DW_TAG_unspecified_type:
+      return 1;
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    case DW_TAG_pointer_type:
+    case DW_TAG_reference_type:
+    case DW_TAG_rvalue_reference_type:
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:
+      if(subtype->full_type)
+        subtype = subtype->full_type;
+      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));
-          switch_types = 1;
-        }
-      }
-      elm_size = subsubtype->size;
+    case DW_TAG_const_type:
+    case DW_TAG_typedef:
+    case DW_TAG_volatile_type:
+      subsubtype = subtype->subtype;
+      if(subsubtype->full_type)
+          subsubtype = subsubtype->full_type;
+      elm_size = subsubtype->byte_size;
       break;
     default : 
       return 0;
       break;
     }
-    for(i=0; i<type->size; 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);
-      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);
+    for(i=0; i<type->element_count; i++){
+      res = compare_areas_with_type((char *)area1 + (i*elm_size), (char *)area2 + (i*elm_size), snapshot1, snapshot2, 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){
-      addr_pointed1 = *((void **)(area1)); 
-      addr_pointed2 = *((void **)(area2));
+  case DW_TAG_pointer_type:
+  case DW_TAG_reference_type:
+  case DW_TAG_rvalue_reference_type:
+
+    addr_pointed1 = *((void **)(area1));
+    addr_pointed2 = *((void **)(area2));
+
+    if(type->subtype && type->subtype->type == DW_TAG_subroutine_type){
       return (addr_pointed1 != addr_pointed2);
     }else{
-      addr_pointed1 = *((void **)(area1)); 
-      addr_pointed2 = *((void **)(area2));
       
       if(addr_pointed1 == NULL && addr_pointed2 == NULL)
         return 0;
-      if(already_compared_pointers(addr_pointed1, addr_pointed2) != -1)
+      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, snapshot1, snapshot2, NULL, type->subtype, 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{
+        else {
+          void* translated_addr_pointer1 = mc_translate_address((uintptr_t)addr_pointed1, snapshot1);
+          void* translated_addr_pointer2 = mc_translate_address((uintptr_t)addr_pointed2, snapshot2);
+          return  compare_areas_with_type(
+            translated_addr_pointer1, translated_addr_pointer2, snapshot1, snapshot2, 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:
+  case DW_TAG_class_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);
+      void* member1 = mc_member_snapshot_resolve(area1, type, member, snapshot1);
+      void* member2 = mc_member_snapshot_resolve(area2, type, member, snapshot2);
+      res = compare_areas_with_type(member1, member2, snapshot1, snapshot2, 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:
@@ -232,43 +227,46 @@ static int compare_areas_with_type(void *area1, void *area2, xbt_dict_t types, x
   return 0;
 }
 
-static int compare_global_variables(int region_type, mc_mem_region_t r1, mc_mem_region_t r2){
+static int compare_global_variables(int region_type, mc_mem_region_t r1, mc_mem_region_t r2, mc_snapshot_t snapshot1, mc_snapshot_t snapshot2){
 
   if(!compared_pointers){
     compared_pointers = xbt_dynar_new(sizeof(pointers_pair_t), pointers_pair_free_voidp);
-    MC_ignore_global_variable("compared_pointers");
   }else{
     xbt_dynar_reset(compared_pointers);
   }
 
   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;
   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;
     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;
     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, snapshot1, snapshot2, 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);
@@ -285,11 +283,12 @@ 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){
+static int compare_local_variables(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2, 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);
-    MC_ignore_global_variable("compared_pointers");
   }else{
     xbt_dynar_reset(compared_pointers);
   }
@@ -313,10 +312,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, snapshot1, snapshot2, 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, snapshot1, snapshot2, 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 +370,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 +424,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){
@@ -492,7 +456,7 @@ int snapshot_compare(void *state1, void *state2){
   while(cursor < xbt_dynar_length(s1->stacks)){
     stack1 = (mc_snapshot_stack_t)xbt_dynar_get_as(s1->stacks, cursor, mc_snapshot_stack_t);
     stack2 = (mc_snapshot_stack_t)xbt_dynar_get_as(s2->stacks, cursor, mc_snapshot_stack_t);
-    diff_local = compare_local_variables(stack1, stack2, s1->regions[0]->data, s2->regions[0]->data);
+    diff_local = compare_local_variables(s1, s2, stack1, stack2, s1->regions[0]->data, s2->regions[0]->data);
     if(diff_local > 0){
       #ifdef MC_DEBUG
         if(is_diff == 0){
@@ -521,55 +485,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], s1, s2);
   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 +527,15 @@ 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(s1, s2, (xbt_mheap_t)s1->regions[0]->data,
+                            (xbt_mheap_t)s2->regions[0]->data) > 0){
 
     #ifdef MC_DEBUG
       xbt_os_walltimer_stop(timer);
@@ -630,7 +579,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;
   
 }
 
@@ -657,8 +624,7 @@ int SIMIX_pre_mc_compare_snapshots(smx_simcall_t simcall,
 }
 
 int MC_compare_snapshots(void *s1, void *s2){
-  
-  MC_ignore_local_variable("self", "simcall_BODY_mc_snapshot");
+
   return simcall_mc_compare_snapshots(s1, s2);
 
 }
index fb3c120..5ab8aed 100644 (file)
@@ -13,9 +13,161 @@ 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++;
+  }
+}
+
+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->src_host = simcall_host_get_name(pattern->comm->comm.src_proc->smx_host);
+        current_pattern->dst_proc = pattern->comm->comm.dst_proc->pid;
+        current_pattern->dst_host = simcall_host_get_name(pattern->comm->comm.dst_proc->smx_host);
+        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->dst_host = simcall_host_get_name(pattern->comm->comm.dst_proc->smx_host);
+    }
+    pattern->src_proc = pattern->comm->comm.src_proc->pid;
+    pattern->src_host = simcall_host_get_name(request->issuer->smx_host);
+    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->src_host = simcall_host_get_name(pattern->comm->comm.src_proc->smx_host);
+      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;
+    pattern->dst_host = simcall_host_get_name(request->issuer->smx_host);
+  }
+  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){
+    if(current_comm->type == SIMIX_COMM_SEND)
+      XBT_INFO("[(%lu) %s -> %s] %s ", current_comm->src_proc, current_comm->src_host, current_comm->dst_host, "iSend");
+    else
+      XBT_INFO("[(%lu) %s <- %s] %s ", current_comm->dst_proc, current_comm->dst_host, current_comm->src_host, "iRecv");
+  }
+}
+
 static void visited_state_free(mc_visited_state_t state){
   if(state){
     MC_free_snapshot(state->system_state);
@@ -27,6 +179,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,7 +197,25 @@ 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){
+  XBT_VERB("Searching interval for state %i: nd_processes=%zu heap_bytes_used=%zu",
+    state->num, (size_t)state->nb_processes, (size_t)state->heap_bytes_used);
 
   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
 
@@ -95,6 +269,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 +303,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 +322,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 +337,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 +364,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 +380,8 @@ static int is_visited_state(){
           min2 = state_test->num;
         }
       }
+
+      // and drop it:
       xbt_dynar_remove_at(visited_states, index2, NULL);
     }
 
@@ -210,12 +407,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 +465,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 +474,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 +495,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 +525,29 @@ void MC_dpor(void)
       xbt_dict_remove(first_enabled_state, key); 
       xbt_free(key);
       MC_UNSET_RAW_MEM;
+      
+      if(_sg_mc_comms_determinism || _sg_mc_send_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 || _sg_mc_send_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 +639,45 @@ void MC_dpor(void)
 
       }
 
-      /* Trash the current state, no longer needed */
       MC_SET_RAW_MEM;
+
+      if(_sg_mc_comms_determinism || _sg_mc_send_determinism){
+        if(initial_state_safety->initial_communications_pattern_done){
+          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);
+            if(initial_state_safety->comm_deterministic == 0 && _sg_mc_comms_determinism){
+              XBT_INFO("****************************************************");
+              XBT_INFO("***** Non-deterministic communications pattern *****");
+              XBT_INFO("****************************************************");
+              XBT_INFO("Initial communications pattern:");
+              print_communications_pattern(initial_communications_pattern);
+              XBT_INFO("Communications pattern counter-example:");
+              print_communications_pattern(communications_pattern);
+              MC_print_statistics(mc_stats);
+              return;
+            }else if(initial_state_safety->send_deterministic == 0 && _sg_mc_send_determinism){
+              XBT_INFO("****************************************************");
+              XBT_INFO("***** Non-send-deterministic communications pattern *****");
+              XBT_INFO("****************************************************");
+              XBT_INFO("Initial communications pattern:");
+              print_communications_pattern(initial_communications_pattern);
+              XBT_INFO("Communications pattern counter-example:");
+              print_communications_pattern(communications_pattern);
+              MC_print_statistics(mc_stats);
+              return;
+            }
+          }
+        }else{
+          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 +743,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 +764,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 (file)
index 0000000..d82ee7d
--- /dev/null
@@ -0,0 +1,823 @@
+/* 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 <stdlib.h>
+#include <dwarf.h>
+#include <elfutils/libdw.h>
+#include <inttypes.h>
+
+#include <simgrid_config.h>
+#include <xbt/log.h>
+#include <xbt/sysdep.h>
+
+#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, const char* namespace);
+
+/** \brief Process a type DIE
+ */
+static void MC_dwarf_handle_type_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame, const char* namespace);
+
+/** \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, const char* namespace);
+
+/** \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, const char* namespace);
+
+/** \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_unknown";
+  }
+}
+
+/** \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_unknown";
+  }
+}
+
+/** \brief A class of DWARF tags (DW_TAG_*)
+ */
+typedef enum mc_tag_class {
+  mc_tag_unknown,
+  mc_tag_type,
+  mc_tag_subprogram,
+  mc_tag_variable,
+  mc_tag_scope,
+  mc_tag_namespace
+} mc_tag_class;
+
+static mc_tag_class MC_dwarf_tag_classify(int tag) {
+  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_reference_type:
+    case DW_TAG_rvalue_reference_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:
+      return mc_tag_type;
+
+    case DW_TAG_subprogram:
+      return mc_tag_subprogram;
+
+    case DW_TAG_variable:
+    case DW_TAG_formal_parameter:
+      return mc_tag_variable;
+
+    case DW_TAG_lexical_block:
+    case DW_TAG_try_block:
+    case DW_TAG_inlined_subroutine:
+      return mc_tag_scope;
+
+    case DW_TAG_namespace:
+      return mc_tag_namespace;
+
+    default:
+      return mc_tag_unknown;
+
+  }
+}
+
+#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_data1:
+  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;
+}
+
+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;
+}
+
+// ***** 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 form = dwarf_whatform(&attr);
+  int klass = MC_dwarf_form_get_class(form);
+  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 {
+        mc_dwarf_expression_init(&member->location, len, expr);
+      }
+      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 (%i) / form 0x%x as DW_AT_member_location",
+      klass, form);
+  }
+
+}
+
+static void dw_type_free_voidp(void *t){
+  dw_type_free((dw_type_t) * (void **) t);
+}
+
+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_voidp);
+  for (res=dwarf_child(die, &child); res==0; res=dwarf_siblingof(&child,&child)) {
+    int tag = dwarf_tag(&child);
+    if (tag==DW_TAG_member || tag==DW_TAG_inheritance) {
+
+      // Skip declarations:
+      if (MC_dwarf_attr_flag(&child, DW_AT_declaration, false))
+        continue;
+
+      // Skip compile time constants:
+      if(dwarf_hasattr(&child, DW_AT_const_value))
+        continue;
+
+      // 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 = tag;
+
+      // Global Offset:
+      member->id = (void *) dwarf_dieoffset(&child);
+
+      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_frame_t frame, const char* namespace) {
+
+  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* prefix = "";
+  switch (type->type) {
+  case DW_TAG_structure_type:
+    prefix = "struct ";
+    break;
+  case DW_TAG_union_type:
+    prefix = "union ";
+    break;
+  case DW_TAG_class_type:
+    prefix = "class ";
+    break;
+  default:
+    prefix = "";
+  }
+
+  const char* name = MC_dwarf_attr_string(die, DW_AT_name);
+  if (name!=NULL) {
+    type->name = namespace ? bprintf("%s%s::%s", prefix, namespace, name) : bprintf("%s%s", prefix, 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);
+         char* new_namespace = namespace == NULL ? xbt_strdup(type->name)
+           : bprintf("%s::%s", namespace, name);
+         MC_dwarf_handle_children(info, die, unit, frame, new_namespace);
+         free(new_namespace);
+         break;
+  }
+
+  return type;
+}
+
+static void MC_dwarf_handle_type_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame, const char* namespace) {
+  dw_type_t type = MC_dwarf_die_to_type(info, die, unit, frame, namespace);
+
+  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->full_types_by_name, type->name, type, NULL);
+  }
+}
+
+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, const char* namespace) {
+  // Skip declarations:
+  if (MC_dwarf_attr_flag(die, DW_AT_declaration, false))
+    return NULL;
+
+  // Skip compile time constants:
+  if(dwarf_hasattr(die, DW_AT_const_value))
+    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
+
+  const char* name = MC_dwarf_attr_string(die, DW_AT_name);
+  variable->name = xbt_strdup(name);
+
+  variable->type_origin = MC_dwarf_at_type(die);
+
+  int form = dwarf_whatform(&attr_location);
+  int klass = form == DW_FORM_sec_offset ? MC_DW_CLASS_CONSTANT : MC_dwarf_form_get_class(form);
+  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 {
+        mc_dwarf_location_list_init_from_expression(&variable->locations, len, expr);
+      }
+
+      break;
+    }
+  case MC_DW_CLASS_LOCLISTPTR:
+  case MC_DW_CLASS_CONSTANT:
+    // Reference to location list:
+    mc_dwarf_location_list_init(&variable->locations, info, die, &attr_location);
+    break;
+  default:
+    xbt_die("Unexpected form 0x%x (%i), class 0x%x (%i) list for location in <%p>%s",
+      form, form, klass, klass, (void*) variable->dwarf_offset, variable->name);
+  }
+
+  // Handle start_scope:
+  if (dwarf_hasattr(die, DW_AT_start_scope)) {
+    Dwarf_Attribute attr;
+    dwarf_attr(die, DW_AT_start_scope, &attr);
+    int form  = dwarf_whatform(&attr);
+    int klass = MC_dwarf_form_get_class(form);
+    switch(klass) {
+    case MC_DW_CLASS_CONSTANT:
+    {
+      Dwarf_Word value;
+      variable->start_scope = dwarf_formudata(&attr, &value) == 0 ? (size_t) value : 0;
+      break;
+    }
+    default:
+      xbt_die("Unhandled form 0x%x, class 0x%X for DW_AT_start_scope of variable %s",
+        form, klass, name==NULL ? "?" : name);
+    }
+  }
+
+  if(namespace && variable->global) {
+    char* old_name = variable->name;
+    variable->name = bprintf("%s::%s", namespace, old_name);
+    free(old_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, const char* namespace) {
+  dw_variable_t variable = MC_die_to_variable(info, die, unit, frame, namespace);
+  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, const char* namespace) {
+
+  // (Template) Subprogram declaration:
+  if (MC_dwarf_attr_flag(die, DW_AT_declaration, false))
+    return;
+
+  dw_frame_t frame = xbt_new0(s_dw_frame_t, 1);
+
+  frame->start = dwarf_dieoffset(die);
+
+  const char* name = MC_dwarf_attr_string(die, DW_AT_name);
+  frame->name = namespace ? bprintf("%s::%s", namespace, 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);
+
+  Dwarf_Attribute attr_frame_base;
+  if (dwarf_attr_integrate(die, DW_AT_frame_base, &attr_frame_base))
+    mc_dwarf_location_list_init(&frame->frame_base, info, die, &attr_frame_base);
+
+  frame->end = -1; // This one is now useless:
+
+  // Register it:
+  const char* key = bprintf("%" PRIx64, (uint64_t) frame->start);
+  xbt_dict_set(info->subprograms,  key, frame, NULL);
+
+  // Handle children:
+  MC_dwarf_handle_children(info, die, unit, frame, namespace);
+}
+
+static void mc_dwarf_handle_namespace_die(
+    mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame, const char* namespace) {
+  const char* name = MC_dwarf_attr_string(die, DW_AT_name);
+  if(frame)
+    xbt_die("Unexpected namespace in a subprogram");
+  char* new_namespace = namespace == NULL ? xbt_strdup(name)
+    : bprintf("%s::%s", namespace, name);
+  MC_dwarf_handle_children(info, die, unit, frame, new_namespace);
+}
+
+static void MC_dwarf_handle_children(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame, const char* namespace) {
+  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, namespace);
+  }
+}
+
+static void MC_dwarf_handle_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame, const char* namespace) {
+  int tag = dwarf_tag(die);
+  mc_tag_class klass = MC_dwarf_tag_classify(tag);
+  switch (klass) {
+
+    // Type:
+    case mc_tag_type:
+      MC_dwarf_handle_type_die(info, die, unit, frame, namespace);
+      break;
+
+    // Program:
+    case mc_tag_subprogram:
+      MC_dwarf_handle_subprogram_die(info, die, unit, frame, namespace);
+      return;
+
+    // Variable:
+    case mc_tag_variable:
+      MC_dwarf_handle_variable_die(info, die, unit, frame, namespace);
+      break;
+
+    // Scope:
+    case mc_tag_scope:
+      // TODO
+      break;
+
+    case mc_tag_namespace:
+      mc_dwarf_handle_namespace_die(info, die, unit, frame, namespace);
+      break;
+
+    default:
+      break;
+
+  }
+}
+
+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 unit_die;
+
+    if(dwarf_offdie(dwarf, offset+length, &unit_die)!=NULL) {
+      Dwarf_Die child;
+      int res;
+      for (res=dwarf_child(&unit_die, &child); res==0; res=dwarf_siblingof(&child,&child)) {
+        MC_dwarf_handle_die(info, &child, &unit_die, NULL, 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 (file)
index 0000000..1ea8182
--- /dev/null
@@ -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_expression.c b/src/mc/mc_dwarf_expression.c
new file mode 100644 (file)
index 0000000..0bc9dcc
--- /dev/null
@@ -0,0 +1,371 @@
+
+#include <stdint.h>
+#include <stdarg.h>
+
+#include <dwarf.h>
+#include <elfutils/libdw.h>
+
+#include "mc_private.h"
+
+static int mc_dwarf_push_value(mc_expression_state_t state, Dwarf_Off value) {
+  if(state->stack_size>=MC_EXPRESSION_STACK_SIZE)
+    return MC_EXPRESSION_E_STACK_OVERFLOW;
+
+  state->stack[state->stack_size++] = value;
+  return 0;
+}
+
+int mc_dwarf_execute_expression(
+  size_t n, const Dwarf_Op* ops, mc_expression_state_t state) {
+  for(int i=0; i!=n; ++i) {
+    int error = 0;
+    const Dwarf_Op* op = ops + i;
+    uint8_t atom = op->atom;
+
+    switch (atom) {
+
+    // Registers:
+
+    case DW_OP_breg0: case DW_OP_breg1: case DW_OP_breg2: case DW_OP_breg3:
+    case DW_OP_breg4: case DW_OP_breg5: case DW_OP_breg6: case DW_OP_breg7:
+    case DW_OP_breg8: case DW_OP_breg9: case DW_OP_breg10: case DW_OP_breg11:
+    case DW_OP_breg12: case DW_OP_breg13: case DW_OP_breg14: case DW_OP_breg15:
+    case DW_OP_breg16: case DW_OP_breg17: case DW_OP_breg18: case DW_OP_breg19:
+    case DW_OP_breg20: case DW_OP_breg21: case DW_OP_breg22: case DW_OP_breg23:
+    case DW_OP_breg24: case DW_OP_breg25: case DW_OP_breg26: case DW_OP_breg27:
+    case DW_OP_breg28: case DW_OP_breg29: case DW_OP_breg30: case DW_OP_breg31:{
+        int register_id = op->atom - DW_OP_breg0;
+        unw_word_t res;
+        if(!state->cursor)
+          return MC_EXPRESSION_E_MISSING_STACK_CONTEXT;
+        unw_get_reg(state->cursor, register_id, &res);
+        error = mc_dwarf_push_value(state, res + op->number);
+        break;
+      }
+
+    // Push the CFA (Call Frame Addresse):
+    case DW_OP_call_frame_cfa:
+    {
+      unw_word_t res;
+
+      int register_id =
+#if defined(UNW_TARGET_X86_64)
+          UNW_X86_64_CFA
+#elif defined(UNW_TARGET_X86)
+          UNW_X86_CFA
+#else
+          -1;
+#endif
+        ;
+      if(register_id<0)
+        xbt_die("Support for CFA not implemented for this achitecture.");
+
+      if(!state->cursor)
+        return MC_EXPRESSION_E_MISSING_STACK_CONTEXT;
+
+      unw_get_reg(state->cursor, register_id, &res);
+      error = mc_dwarf_push_value(state, res + op->number);
+      break;
+    }
+
+    // Frame base:
+
+    case DW_OP_fbreg:
+      {
+        if(!state->frame_base)
+          return MC_EXPRESSION_E_MISSING_FRAME_BASE;
+        error = mc_dwarf_push_value(state, ((uintptr_t)state->frame_base) + op->number);
+        break;
+      }
+
+    // Constants:
+
+    case DW_OP_lit0: case DW_OP_lit1: case DW_OP_lit2: case DW_OP_lit3:
+    case DW_OP_lit4: case DW_OP_lit5: case DW_OP_lit6: case DW_OP_lit7:
+    case DW_OP_lit8: case DW_OP_lit9: case DW_OP_lit10: case DW_OP_lit11:
+    case DW_OP_lit12: case DW_OP_lit13: case DW_OP_lit14: case DW_OP_lit15:
+    case DW_OP_lit16: case DW_OP_lit17: case DW_OP_lit18: case DW_OP_lit19:
+    case DW_OP_lit20: case DW_OP_lit21: case DW_OP_lit22: case DW_OP_lit23:
+    case DW_OP_lit24: case DW_OP_lit25: case DW_OP_lit26: case DW_OP_lit27:
+    case DW_OP_lit28: case DW_OP_lit29: case DW_OP_lit30: case DW_OP_lit31:
+      error = mc_dwarf_push_value(state, atom - DW_OP_lit0);
+      break;
+
+    case DW_OP_addr:
+    case DW_OP_const1u:
+    case DW_OP_const2u:
+    case DW_OP_const4u:
+    case DW_OP_const8u:
+    case DW_OP_const1s:
+    case DW_OP_const2s:
+    case DW_OP_const4s:
+    case DW_OP_const8s:
+    case DW_OP_constu:
+    case DW_OP_consts:
+      if(state->stack_size==MC_EXPRESSION_STACK_SIZE)
+        return MC_EXPRESSION_E_STACK_OVERFLOW;
+      error = mc_dwarf_push_value(state, op->number);
+      break;
+
+    // Stack manipulation:
+
+    // Push the value at the top of the stack:
+    case DW_OP_dup:
+      if(state->stack_size==0)
+        return MC_EXPRESSION_E_STACK_UNDERFLOW;
+      else
+        error = mc_dwarf_push_value(state, state->stack[state->stack_size-1]);
+      break;
+
+    case DW_OP_drop:
+      if(state->stack_size==0)
+        return MC_EXPRESSION_E_STACK_UNDERFLOW;
+      else
+        state->stack_size--;
+      break;
+
+    case DW_OP_swap:
+      if(state->stack_size<2)
+        return MC_EXPRESSION_E_STACK_UNDERFLOW;
+      {
+        uintptr_t temp = state->stack[state->stack_size-2];
+        state->stack[state->stack_size-2] = state->stack[state->stack_size-1];
+        state->stack[state->stack_size-1] = temp;
+      }
+      break;
+
+    case DW_OP_over:
+      if(state->stack_size<2)
+        return MC_EXPRESSION_E_STACK_UNDERFLOW;
+      error = mc_dwarf_push_value(state, state->stack[state->stack_size-2]);
+      break;
+
+    // Operations:
+
+    case DW_OP_plus:
+      if(state->stack_size<2)
+        return MC_EXPRESSION_E_STACK_UNDERFLOW;
+      {
+        uintptr_t result = state->stack[state->stack_size-2] + state->stack[state->stack_size-1];
+        state->stack[state->stack_size-2] = result;
+        state->stack_size--;
+      }
+      break;
+
+    case DW_OP_mul:
+      if(state->stack_size<2)
+        return MC_EXPRESSION_E_STACK_UNDERFLOW;
+      {
+        uintptr_t result = state->stack[state->stack_size-2] - state->stack[state->stack_size-1];
+        state->stack[state->stack_size-2] = result;
+        state->stack_size--;
+      }
+      break;
+
+    case DW_OP_plus_uconst:
+      if(state->stack_size==0)
+        return MC_EXPRESSION_E_STACK_UNDERFLOW;
+      state->stack[state->stack_size-1] += op->number;
+      break;
+
+    case DW_OP_not:
+      if(state->stack_size==0)
+        return MC_EXPRESSION_E_STACK_UNDERFLOW;
+      state->stack[state->stack_size-1] = ~state->stack[state->stack_size-1];
+      break;
+
+    case DW_OP_neg:
+      if(state->stack_size==0)
+        return MC_EXPRESSION_E_STACK_UNDERFLOW;
+      {
+        intptr_t value = state->stack[state->stack_size-1];
+        if(value<0) value = -value;
+        state->stack[state->stack_size-1] = value;
+      }
+      break;
+
+    case DW_OP_minus:
+      if(state->stack_size<2)
+        return MC_EXPRESSION_E_STACK_UNDERFLOW;
+      {
+        uintptr_t result = state->stack[state->stack_size-2] - state->stack[state->stack_size-1];
+        state->stack[state->stack_size-2] = result;
+        state->stack_size--;
+      }
+      break;
+
+    case DW_OP_and:
+      if(state->stack_size<2)
+        return MC_EXPRESSION_E_STACK_UNDERFLOW;
+      {
+        uintptr_t result = state->stack[state->stack_size-2] & state->stack[state->stack_size-1];
+        state->stack[state->stack_size-2] = result;
+        state->stack_size--;
+      }
+      break;
+
+    case DW_OP_or:
+      if(state->stack_size<2)
+        return MC_EXPRESSION_E_STACK_UNDERFLOW;
+      {
+        uintptr_t result = state->stack[state->stack_size-2] | state->stack[state->stack_size-1];
+        state->stack[state->stack_size-2] = result;
+        state->stack_size--;
+      }
+      break;
+
+    case DW_OP_xor:
+      if(state->stack_size<2)
+        return MC_EXPRESSION_E_STACK_UNDERFLOW;
+      {
+        uintptr_t result = state->stack[state->stack_size-2] ^ state->stack[state->stack_size-1];
+        state->stack[state->stack_size-2] = result;
+        state->stack_size--;
+      }
+      break;
+
+    case DW_OP_nop:
+      break;
+
+    // Dereference:
+    case DW_OP_deref_size:
+      return MC_EXPRESSION_E_UNSUPPORTED_OPERATION;
+
+    case DW_OP_deref:
+      if(state->stack_size==0)
+        return MC_EXPRESSION_E_STACK_UNDERFLOW;
+      {
+        // Computed address:
+        uintptr_t address = (uintptr_t) state->stack[state->stack_size-1];
+        uintptr_t* p = (uintptr_t*)mc_translate_address(address, state->snapshot);
+        state->stack[state->stack_size-1] = *p;
+      }
+      break;
+
+    // Not handled:
+    default:
+     return MC_EXPRESSION_E_UNSUPPORTED_OPERATION;
+    }
+
+    if(error) return error;
+  }
+  return 0;
+}
+
+// ***** Location
+
+/** \brief Resolve a location expression
+ *  \deprecated Use mc_dwarf_resolve_expression
+ */
+Dwarf_Off mc_dwarf_resolve_location(mc_expression_t expression, unw_cursor_t* c, void* frame_pointer_address, mc_snapshot_t snapshot) {
+  s_mc_expression_state_t state;
+  memset(&state, 0, sizeof(s_mc_expression_state_t));
+  state.frame_base = frame_pointer_address;
+  state.cursor = c;
+  state.snapshot = snapshot;
+
+  if(mc_dwarf_execute_expression(expression->size, expression->ops, &state))
+    xbt_die("Error evaluating DWARF expression");
+  if(state.stack_size==0)
+    xbt_die("No value on the stack");
+  else
+    return (Dwarf_Off) state.stack[state.stack_size-1];
+}
+
+Dwarf_Off mc_dwarf_resolve_locations(mc_location_list_t locations, unw_cursor_t* c, void* frame_pointer_address, mc_snapshot_t snapshot) {
+
+  unw_word_t ip;
+  if(c) {
+    if(unw_get_reg(c, UNW_REG_IP, &ip))
+      xbt_die("Could not resolve IP");
+  }
+
+  for(size_t i=0; i!=locations->size; ++i) {
+    mc_expression_t expression = locations->locations + i;
+    if( (expression->lowpc==NULL && expression->highpc==NULL)
+      || (c && ip >= (unw_word_t) expression->lowpc && ip < (unw_word_t) expression->highpc)) {
+      return mc_dwarf_resolve_location(expression, c, frame_pointer_address, snapshot);
+    }
+  }
+  xbt_die("Could not resolve location");
+}
+
+/** \brief Find the frame base of a given frame
+ *
+ *  \param frame
+ *  \param unw_cursor
+ */
+void* mc_find_frame_base(dw_frame_t frame, unw_cursor_t* unw_cursor) {
+  return (void*) mc_dwarf_resolve_locations(&frame->frame_base, unw_cursor, NULL, NULL);
+}
+
+void mc_dwarf_expression_clear(mc_expression_t expression) {
+  free(expression->ops);
+  expression->ops = NULL;
+  expression->size = 0;
+  expression->lowpc = NULL;
+  expression->highpc = NULL;
+}
+
+void mc_dwarf_location_list_clear(mc_location_list_t list) {
+  for(size_t i=0; i!=list->size; ++i) {
+    mc_dwarf_expression_clear(list->locations + i);
+  }
+  free(list->locations);
+  list->locations = NULL;
+  list->size = 0;
+}
+
+void mc_dwarf_expression_init(mc_expression_t expression, size_t len, Dwarf_Op* ops) {
+  if(expression->ops) {
+    free(expression->ops);
+  }
+  expression->lowpc = NULL;
+  expression->highpc = NULL;
+  expression->size = len;
+  expression->ops = xbt_malloc(len*sizeof(Dwarf_Op));
+  memcpy(expression->ops, ops, len*sizeof(Dwarf_Op));
+}
+
+void mc_dwarf_location_list_init_from_expression(mc_location_list_t target, size_t len, Dwarf_Op* ops) {
+  if(target->locations) {
+    mc_dwarf_location_list_clear(target);
+  }
+  target->size = 1;
+  target->locations = (mc_expression_t) xbt_malloc(sizeof(s_mc_expression_t));
+  mc_dwarf_expression_init(target->locations, len, ops);
+}
+
+void mc_dwarf_location_list_init(mc_location_list_t list, mc_object_info_t info, Dwarf_Die* die, Dwarf_Attribute* attr) {
+  if(list->locations) {
+    mc_dwarf_location_list_clear(list);
+  }
+  list->size = 0;
+
+  ptrdiff_t offset = 0;
+  Dwarf_Addr base, start, end;
+  Dwarf_Op *ops;
+  size_t len;
+
+  while (1) {
+
+    offset = dwarf_getlocations(attr, offset, &base, &start, &end, &ops, &len);
+    if (offset==0)
+      return;
+    else if (offset==-1)
+      xbt_die("Error while loading location list");
+
+    int i = list->size;
+    list->size++;
+    list->locations = (mc_expression_t) realloc(list->locations, list->size*sizeof(s_mc_expression_t));
+    mc_expression_t expression = list->locations + i;
+
+    void* base = info->flags & MC_OBJECT_INFO_EXECUTABLE ? 0 : MC_object_base_address(info);
+    mc_dwarf_expression_init(expression, len, ops);
+
+    // If start == 0, this is not a location list:
+    expression->lowpc = start == 0 ? NULL : (char*) base + start;
+    expression->highpc = start == 0 ? NULL : (char*) base + end;
+  }
+
+}
diff --git a/src/mc/mc_dwarf_tagnames.h b/src/mc/mc_dwarf_tagnames.h
new file mode 100644 (file)
index 0000000..98b883a
--- /dev/null
@@ -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";
index 16ebebe..0c6c04d 100644 (file)
@@ -8,6 +8,7 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <sys/time.h>
+#include <libgen.h>
 
 #include "simgrid/sg_config.h"
 #include "../surf/surf_private.h"
@@ -29,9 +30,12 @@ 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 _sg_mc_send_determinism=0;
 
 int user_max_depth_reached = 0;
 
@@ -69,6 +73,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 +101,20 @@ 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);
+}
+
+void _mc_cfg_cb_send_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 send-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_send_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 +135,13 @@ 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;
+
+mc_object_info_t mc_object_infos[2] = { NULL, NULL };
+size_t mc_object_infos_size = 2;
 
 /* 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;
 
@@ -133,291 +155,190 @@ const char* colors[13];
 
 /************************** Free functions *************************/
 
-static void dw_location_free(dw_location_t l){
-  if(l){
-    if(l->type == e_dw_loclist)
-      xbt_dynar_free(&(l->location.loclist));
-    else if(l->type == e_dw_compose)
-      xbt_dynar_free(&(l->location.compose));
-    else if(l->type == e_dw_arithmetic)
-      xbt_free(l->location.arithmetic);
-  
-    xbt_free(l);
-  }
-}
-
-static void dw_location_entry_free(dw_location_entry_t e){
-  dw_location_free(e->location);
-  xbt_free(e);
+void mc_frame_free(dw_frame_t frame){
+  xbt_free(frame->name);
+  mc_dwarf_location_list_clear(&(frame->frame_base));
+  xbt_dynar_free(&(frame->variables));
+  xbt_free(frame);
 }
 
-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));
+  mc_dwarf_expression_clear(&t->location);
   xbt_free(t);
 }
 
-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);
+
+    if(v->locations.locations)
+      mc_dwarf_location_list_clear(&v->locations);
     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);
 }
 
-/*************************************************************************/
-
-static dw_location_t MC_dwarf_get_location(xbt_dict_t location_list, char *expr){
+// ***** object_info
 
-  dw_location_t loc = xbt_new0(s_dw_location_t, 1);
 
-  if(location_list != NULL){
-    
-    char *key = bprintf("%lu", strtoul(expr, NULL, 16));
-    loc->type = e_dw_loclist;
-    loc->location.loclist =  (xbt_dynar_t)xbt_dict_get_or_null(location_list, key);
-    if(loc->location.loclist == NULL)
-      XBT_INFO("Key not found in loclist");
-    xbt_free(key);
-    return loc;
-
-  }else{
-
-    int cursor = 0;
-    char *tok = NULL, *tok2 = NULL; 
-    
-    xbt_dynar_t tokens1 = xbt_str_split(expr, ";");
-    xbt_dynar_t tokens2;
-
-    loc->type = e_dw_compose;
-    loc->location.compose = xbt_dynar_new(sizeof(dw_location_t), NULL);
-
-    while(cursor < xbt_dynar_length(tokens1)){
-
-      tok = xbt_dynar_get_as(tokens1, cursor, char*);
-      tokens2 = xbt_str_split(tok, " ");
-      tok2 = xbt_dynar_get_as(tokens2, 0, char*);
-      
-      if(strncmp(tok2, "DW_OP_reg", 9) == 0){
-        dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
-        new_element->type = e_dw_register;
-        new_element->location.reg = atoi(strtok(tok2, "DW_OP_reg"));
-        xbt_dynar_push(loc->location.compose, &new_element);     
-      }else if(strcmp(tok2, "DW_OP_fbreg:") == 0){
-        dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
-        new_element->type = e_dw_fbregister_op;
-        new_element->location.fbreg_op = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
-        xbt_dynar_push(loc->location.compose, &new_element);
-      }else if(strncmp(tok2, "DW_OP_breg", 10) == 0){
-        dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
-        new_element->type = e_dw_bregister_op;
-        new_element->location.breg_op.reg = atoi(strtok(tok2, "DW_OP_breg"));
-        new_element->location.breg_op.offset = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
-        xbt_dynar_push(loc->location.compose, &new_element);
-      }else if(strncmp(tok2, "DW_OP_lit", 9) == 0){
-        dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
-        new_element->type = e_dw_lit;
-        new_element->location.lit = atoi(strtok(tok2, "DW_OP_lit"));
-        xbt_dynar_push(loc->location.compose, &new_element);
-      }else if(strcmp(tok2, "DW_OP_piece:") == 0){
-        dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
-        new_element->type = e_dw_piece;
-        new_element->location.piece = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
-        xbt_dynar_push(loc->location.compose, &new_element);
-      }else if(strcmp(tok2, "DW_OP_plus_uconst:") == 0){
-        dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
-        new_element->type = e_dw_plus_uconst;
-        new_element->location.plus_uconst = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char *));
-        xbt_dynar_push(loc->location.compose, &new_element);
-      }else if(strcmp(tok, "DW_OP_abs") == 0 || 
-               strcmp(tok, "DW_OP_and") == 0 ||
-               strcmp(tok, "DW_OP_div") == 0 ||
-               strcmp(tok, "DW_OP_minus") == 0 ||
-               strcmp(tok, "DW_OP_mod") == 0 ||
-               strcmp(tok, "DW_OP_mul") == 0 ||
-               strcmp(tok, "DW_OP_neg") == 0 ||
-               strcmp(tok, "DW_OP_not") == 0 ||
-               strcmp(tok, "DW_OP_or") == 0 ||
-               strcmp(tok, "DW_OP_plus") == 0){               
-        dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
-        new_element->type = e_dw_arithmetic;
-        new_element->location.arithmetic = strdup(strtok(tok2, "DW_OP_"));
-        xbt_dynar_push(loc->location.compose, &new_element);
-      }else if(strcmp(tok, "DW_OP_stack_value") == 0){
-      }else if(strcmp(tok2, "DW_OP_deref_size:") == 0){
-        dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
-        new_element->type = e_dw_deref;
-        new_element->location.deref_size = (unsigned int short) atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
-        xbt_dynar_push(loc->location.compose, &new_element);
-      }else if(strcmp(tok, "DW_OP_deref") == 0){
-        dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
-        new_element->type = e_dw_deref;
-        new_element->location.deref_size = sizeof(void *);
-        xbt_dynar_push(loc->location.compose, &new_element);
-      }else if(strcmp(tok2, "DW_OP_constu:") == 0){
-        dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
-        new_element->type = e_dw_uconstant;
-        new_element->location.uconstant.bytes = 1;
-        new_element->location.uconstant.value = (unsigned long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
-        xbt_dynar_push(loc->location.compose, &new_element);
-      }else if(strcmp(tok2, "DW_OP_consts:") == 0){
-        dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
-        new_element->type = e_dw_sconstant;
-        new_element->location.sconstant.bytes = 1;
-        new_element->location.sconstant.value = (long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
-        xbt_dynar_push(loc->location.compose, &new_element);
-      }else if(strcmp(tok2, "DW_OP_const1u:") == 0 ||
-               strcmp(tok2, "DW_OP_const2u:") == 0 ||
-               strcmp(tok2, "DW_OP_const4u:") == 0 ||
-               strcmp(tok2, "DW_OP_const8u:") == 0){
-        dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
-        new_element->type = e_dw_uconstant;
-        new_element->location.uconstant.bytes = tok2[11] - '0';
-        new_element->location.uconstant.value = (unsigned long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
-        xbt_dynar_push(loc->location.compose, &new_element);
-      }else if(strcmp(tok, "DW_OP_const1s") == 0 ||
-               strcmp(tok, "DW_OP_const2s") == 0 ||
-               strcmp(tok, "DW_OP_const4s") == 0 ||
-               strcmp(tok, "DW_OP_const8s") == 0){
-        dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
-        new_element->type = e_dw_sconstant;
-        new_element->location.sconstant.bytes = tok2[11] - '0';
-        new_element->location.sconstant.value = (long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
-        xbt_dynar_push(loc->location.compose, &new_element);
-      }else{
-        dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
-        new_element->type = e_dw_unsupported;
-        xbt_dynar_push(loc->location.compose, &new_element);
-      }
-
-      cursor++;
-      xbt_dynar_free(&tokens2);
-
-    }
-    
-    xbt_dynar_free(&tokens1);
-
-    return loc;
-    
-  }
 
+mc_object_info_t MC_new_object_info(void) {
+  mc_object_info_t res = xbt_new0(s_mc_object_info_t, 1);
+  res->subprograms = xbt_dict_new_homogeneous((void (*)(void*))mc_frame_free);
+  res->global_variables = xbt_dynar_new(sizeof(dw_variable_t), dw_variable_free_voidp);
+  res->types = xbt_dict_new_homogeneous((void (*)(void*))dw_type_free);
+  res->full_types_by_name = xbt_dict_new_homogeneous(NULL);
+  return res;
 }
 
-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");
+void MC_free_object_info(mc_object_info_t* info) {
+  xbt_free(&(*info)->file_name);
+  xbt_dict_free(&(*info)->subprograms);
+  xbt_dynar_free(&(*info)->global_variables);
+  xbt_dict_free(&(*info)->types);
+  xbt_dict_free(&(*info)->full_types_by_name);
+  xbt_free(info);
+  xbt_dynar_free(&(*info)->functions_index);
+  *info = NULL;
+}
 
-  if(fp == NULL){
-    perror("popen for objdump failed");
-    xbt_abort();
-  }
+// ***** Helpers
 
-  int debug = 0; /*Detect if the program has been compiled with -g */
+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;
+}
 
-  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;
+// ***** Functions index
 
-  while ((read = xbt_getline(&line, &n, fp)) != -1) {
+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;
+}
 
-    /* Wipeout the new line character */
-    line[read - 1] = '\0';
+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);
 
-    xbt_str_trim(line, NULL);
-    
-    if(n == 0)
+  // Populate the array:
+  dw_frame_t frame = NULL;
+  xbt_dict_cursor_t cursor;
+  char* key;
+  xbt_dict_foreach(info->subprograms, cursor, key, 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);
+  }
 
-    if(strlen(line) == 0)
-      continue;
+  mc_function_index_item_t base = (mc_function_index_item_t) xbt_dynar_get_ptr(index, 0);
 
-    if(debug == 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);
 
-      if(strncmp(line, elf_file, strlen(elf_file)) == 0)
-        continue;
-      
-      if(strncmp(line, "Contents", 8) == 0)
-        continue;
+  info->functions_index = index;
+}
 
-      if(strncmp(line, "Offset", 6) == 0){
-        debug = 1;
-        continue;
-      }
+mc_object_info_t MC_ip_find_object_info(void* ip) {
+  size_t i;
+  for(i=0; i!=mc_object_infos_size; ++i) {
+    if(ip >= (void*)mc_object_infos[i]->start_exec && ip <= (void*)mc_object_infos[i]->end_exec) {
+      return mc_object_infos[i];
     }
+  }
+  return NULL;
+}
 
-    if(debug == 0){
-      XBT_INFO("Your program must be compiled with -g");
-      xbt_abort();
+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;
+}
 
-    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("<End", (char *)xbt_dynar_get_as(split, 1, char *)) != 0){
-      
-      dw_location_entry_t new_entry = xbt_new0(s_dw_location_entry_t, 1);
-      new_entry->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);
+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);
+}
 
-      xbt_dynar_free(&split);
-      free(loc_expr);
+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);
+    }
+  }
+}
 
-      read = xbt_getline(&line, &n, fp);
-      if(read != -1){
-        line[read - 1] = '\0';
-        xbt_str_strip_spaces(line);
-        split = xbt_str_split(line, " ");
+static void MC_post_process_functions(mc_object_info_t info) {
+  xbt_dict_cursor_t cursor;
+  char* key;
+  dw_frame_t function = NULL;
+  xbt_dict_foreach(info->subprograms, 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);
       }
-
     }
-
-
-    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 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;
 }
 
+/*************************************************************************/
+
+/** \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 +389,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 +402,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 +413,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 +448,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 +468,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,195 +582,75 @@ 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);
+  if(!raw_mem_set)
+    MC_UNSET_RAW_MEM;
+}
 
-    mc_data_bss_ignore_variable_t var = NULL;
-    var = xbt_new0(s_mc_data_bss_ignore_variable_t, 1);
-    var->name = strdup(name);
+static void MC_ignore_local_variable_in_object(const char *var_name, const char *frame_name, mc_object_info_t info) {
+  xbt_dict_cursor_t cursor2;
+  dw_frame_t frame;
+  int start, end;
+  int cursor = 0;
+  dw_variable_t current_var;
+  char* key;
+  xbt_dict_foreach(info->subprograms, cursor2, key, frame) {
 
-    if(xbt_dynar_is_empty(mc_data_bss_comparison_ignore)){
+    if(frame_name && strcmp(frame_name, frame->name))
+      continue;
 
-      xbt_dynar_insert_at(mc_data_bss_comparison_ignore, 0, &var);
+    start = 0;
+    end = xbt_dynar_length(frame->variables) - 1;
+    while(start <= end){
+      cursor = (start + end) / 2;
+      current_var = (dw_variable_t)xbt_dynar_get_as(frame->variables, cursor, dw_variable_t);
 
-    }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;
-        }
+      int compare = strcmp(current_var->name, var_name);
+      if(compare == 0){
+        xbt_dynar_remove_at(frame->variables, cursor, NULL);
+        start = 0;
+        end = xbt_dynar_length(frame->variables) - 1;
+      }else if(compare < 0){
+        start = cursor + 1;
+      }else{
+        end = cursor - 1;
       }
-
-      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;
 }
 
 void MC_ignore_local_variable(const char *var_name, const char *frame_name){
   
   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
 
-  MC_SET_RAW_MEM;
-
-  if(mc_local_variables_libsimgrid){
-    unsigned int cursor = 0;
-    dw_variable_t current_var;
-    int start, end;
-    if(strcmp(frame_name, "*") == 0){ /* Remove variable in all frames */
-      xbt_dict_cursor_t dict_cursor;
-      char *current_frame_name;
-      dw_frame_t frame;
-      xbt_dict_foreach(mc_local_variables_libsimgrid, dict_cursor, current_frame_name, frame){
-        start = 0;
-        end = xbt_dynar_length(frame->variables) - 1;
-        while(start <= end){
-          cursor = (start + end) / 2;
-          current_var = (dw_variable_t)xbt_dynar_get_as(frame->variables, cursor, dw_variable_t); 
-          if(strcmp(current_var->name, var_name) == 0){
-            xbt_dynar_remove_at(frame->variables, cursor, NULL);
-            start = 0;
-            end = xbt_dynar_length(frame->variables) - 1;
-          }else if(strcmp(current_var->name, var_name) < 0){
-            start = cursor + 1;
-          }else{
-            end = cursor - 1;
-          } 
-        }
-      }
-       xbt_dict_foreach(mc_local_variables_binary, dict_cursor, current_frame_name, frame){
-        start = 0;
-        end = xbt_dynar_length(frame->variables) - 1;
-        while(start <= end){
-          cursor = (start + end) / 2;
-          current_var = (dw_variable_t)xbt_dynar_get_as(frame->variables, cursor, dw_variable_t); 
-          if(strcmp(current_var->name, var_name) == 0){
-            xbt_dynar_remove_at(frame->variables, cursor, NULL);
-            start = 0;
-            end = xbt_dynar_length(frame->variables) - 1;
-          }else if(strcmp(current_var->name, var_name) < 0){
-            start = cursor + 1;
-          }else{
-            end = cursor - 1;
-          } 
-        }
-      }
-    }else{
-      xbt_dynar_t variables_list = ((dw_frame_t)xbt_dict_get_or_null(mc_local_variables_libsimgrid, frame_name))->variables;
-      start = 0;
-      end = xbt_dynar_length(variables_list) - 1;
-      while(start <= end){
-        cursor = (start + end) / 2;
-        current_var = (dw_variable_t)xbt_dynar_get_as(variables_list, cursor, dw_variable_t);
-        if(strcmp(current_var->name, var_name) == 0){
-          xbt_dynar_remove_at(variables_list, cursor, NULL);
-          start = 0;
-          end = xbt_dynar_length(variables_list) - 1;
-        }else if(strcmp(current_var->name, var_name) < 0){
-          start = cursor + 1;
-        }else{
-          end = cursor - 1;
-        } 
-      }
-    } 
-  }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)){
+  if(strcmp(frame_name, "*") == 0)
+    frame_name = NULL;
 
-      xbt_dynar_insert_at(mc_stack_comparison_ignore, 0, &var);
+  MC_SET_RAW_MEM;
 
-    }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);
-      }
-    }
-  }
+  MC_ignore_local_variable_in_object(var_name, frame_name, mc_libsimgrid_info);
+  if(frame_name!=NULL)
+    MC_ignore_local_variable_in_object(var_name, frame_name, mc_binary_info);
 
   if(!raw_mem_set)
     MC_UNSET_RAW_MEM;
@@ -1655,44 +742,50 @@ 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;
+static void MC_post_process_object_info(mc_object_info_t info) {
+  xbt_dict_cursor_t cursor = NULL;
+  char* key = NULL;
+  dw_type_t type = NULL;
+  xbt_dict_foreach(info->types, cursor, key, type){
+
+    // Resolve full_type:
+    if(type->name && type->byte_size == 0) {
+      for(size_t i=0; i!=mc_object_infos_size; ++i) {
+        dw_type_t same_type =  xbt_dict_get_or_null(mc_object_infos[i]->full_types_by_name, type->name);
+        if(same_type && same_type->name && same_type->byte_size) {
+          type->full_type = same_type;
+          break;
+        }
+      }
+    }
 
-  xbt_dynar_foreach(mc_stack_comparison_ignore, cursor, current_var){
-    MC_ignore_local_variable(current_var->var_name, current_var->frame);
   }
-
-  xbt_dynar_free(&mc_stack_comparison_ignore);
-  mc_stack_comparison_ignore = NULL;
 }
 
-static void MC_dump_ignored_global_variables(void){
+static void MC_init_debug_info(void) {
+  XBT_INFO("Get debug information ...");
 
-  if(mc_data_bss_comparison_ignore == NULL || xbt_dynar_is_empty(mc_data_bss_comparison_ignore))
-    return;
+  memory_map_t maps = MC_get_memory_map();
 
-  unsigned int cursor = 0;
-  mc_data_bss_ignore_variable_t current_var;
+  /* Get local variables for state equality detection */
+  mc_binary_info = MC_find_object_info(maps, xbt_binary_name, 1);
+  mc_object_infos[0] = mc_binary_info;
 
-  xbt_dynar_foreach(mc_data_bss_comparison_ignore, cursor, current_var){
-    MC_ignore_global_variable(current_var->name);
-  } 
+  mc_libsimgrid_info = MC_find_object_info(maps, libsimgrid_path, 0);
+  mc_object_infos[1] = mc_libsimgrid_info;
 
-  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 +794,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);
@@ -1747,12 +811,14 @@ void MC_init(){
   MC_ignore_local_variable("_throw_ctx", "*");
   MC_ignore_local_variable("ctx", "*");
 
+  MC_ignore_local_variable("self", "simcall_BODY_mc_snapshot");
   MC_ignore_local_variable("next_context", "smx_ctx_sysv_suspend_serial");
   MC_ignore_local_variable("i", "smx_ctx_sysv_suspend_serial");
 
   /* Ignore local variable about time used for tracing */
   MC_ignore_local_variable("start_time", "*"); 
 
+  MC_ignore_global_variable("compared_pointers");
   MC_ignore_global_variable("mc_comp_times");
   MC_ignore_global_variable("mc_snapshot_comparison_time"); 
   MC_ignore_global_variable("mc_time");
@@ -1760,6 +826,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 +932,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 +942,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 +999,7 @@ void MC_modelcheck_liveness(){
 void MC_exit(void)
 {
   xbt_free(mc_time);
+
   MC_memory_exit();
   //xbt_abort();
 }
@@ -1998,6 +1068,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 +1098,8 @@ void MC_replay(xbt_fifo_t stack, int start)
       xbt_free(key);
     }
   }
+  if(_sg_mc_comms_determinism || _sg_mc_send_determinism)
+    xbt_dynar_reset(communications_pattern);
   MC_UNSET_RAW_MEM;
   
 
@@ -2056,8 +1129,25 @@ void MC_replay(xbt_fifo_t stack, int start)
         xbt_free(req_str);
       }
     }
-    
+
+    if(_sg_mc_comms_determinism || _sg_mc_send_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 || _sg_mc_send_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 +1428,12 @@ void MC_print_statistics(mc_stats_t stats)
     fprintf(dot_output, "}\n");
     fclose(dot_output);
   }
+  if(initial_state_safety != NULL){
+    if(_sg_mc_comms_determinism)
+      XBT_INFO("Communication-deterministic : %s", !initial_state_safety->comm_deterministic ? "No" : "Yes");
+    if (_sg_mc_send_determinism)
+      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 (file)
index 0000000..5b824ae
--- /dev/null
@@ -0,0 +1,309 @@
+/* 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 <stdint.h>
+#include <stdbool.h>
+
+#include "mc_private.h"
+#include "mc/datatypes.h"
+#include <mc/mc.h>
+
+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<iend && end>=istart && end<iend)
+     return true;
+  }
+
+  return false;
+}
+
+static void mc_hash_binary(mc_hash_t *hash, const void* s, size_t len) {
+  const char* p = (const void*) s;
+  int i;
+  for(i=0; i!=len; ++i) {
+    MC_HASH(*hash, p[i]);
+  }
+}
+
+/** \brief Compute a hash for a given value of a given type
+ *
+ *  We try to be very conservative (do not hash too ambiguous things).
+ *
+ *  \param address address of the variable
+ *  \param type type of the variable
+ * */
+static void mc_hash_value(mc_hash_t* hash, mc_hashing_state* state, mc_object_info_t info, const void* address, dw_type_t type) {
+  top:
+
+  switch(type->type){
+
+  // Not relevant, do nothing:
+  case DW_TAG_unspecified_type:
+    return;
+
+  // 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;
+      void* member_variable = mc_member_resolve(address, type, member, NULL);
+      mc_hash_value(hash, state, info, member_variable, 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->locations.size == 0) {
+      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_locations(&variable->locations, unw_cursor, frame_pointer, NULL);
+
+    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;
+}
index acc5803..96e6513 100644 (file)
@@ -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_member.c b/src/mc/mc_member.c
new file mode 100644 (file)
index 0000000..d894567
--- /dev/null
@@ -0,0 +1,51 @@
+#include "mc_private.h"
+
+/** Resolve snapshot in the process address space
+ *
+ * @param object   Process address of the struct/class
+ * @param type     Type of the struct/class
+ * @param member   Member description
+ * @param snapshot Snapshot (or NULL)
+ * @return Process address of the given member of the 'object' struct/class
+ */
+void* mc_member_resolve(const void* base, dw_type_t type, dw_type_t member, mc_snapshot_t snapshot) {
+  if(!member->location.size) {
+    return ((char*) base) + member->offset;
+  }
+
+  s_mc_expression_state_t state;
+  memset(&state, 0, sizeof(s_mc_expression_state_t));
+  state.frame_base = NULL;
+  state.cursor = NULL;
+  state.snapshot = snapshot;
+  state.stack_size = 1;
+  state.stack[0] = (uintptr_t) base;
+
+  if(mc_dwarf_execute_expression(member->location.size, member->location.ops, &state))
+    xbt_die("Error evaluating DWARF expression");
+  if(state.stack_size==0)
+    xbt_die("No value on the stack");
+  else
+    return (void*) state.stack[state.stack_size-1];
+}
+
+/** Resolve snapshot in the snapshot address space
+ *
+ * @param  object Snapshot address of the struct/class
+ * @param  type Type of the struct/class
+ * @param  member Member description
+ * @param  snapshot Snapshot (or NULL)
+ * @return Snapshot address of the given member of the 'object' struct/class
+ */
+void* mc_member_snapshot_resolve(const void* object, dw_type_t type, dw_type_t member, mc_snapshot_t snapshot) {
+  if(!member->location.size) {
+    return (char*) object + member->offset;
+  } else {
+    // Translate the problem in the process address space:
+    void* real_area = (void*) mc_untranslate_address((void *)object, snapshot);
+    // Resolve the member in the process address space:
+    void* real_member = mc_member_resolve(real_area, type, member, snapshot);
+    // Translate back in the snapshot address space:
+    return mc_translate_address((uintptr_t)real_member, snapshot);
+  }
+}
index 2253daf..f734ec7 100644 (file)
@@ -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);
 }
index 0f2a556..168fa7a 100644 (file)
@@ -12,6 +12,8 @@
 #ifndef WIN32
 #include <sys/mman.h>
 #endif
+#include <elfutils/libdw.h>
+
 #include "mc/mc.h"
 #include "mc/datatypes.h"
 #include "xbt/fifo.h"
 #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)*/ 
 
 typedef struct s_mc_mem_region{
+  // Real address:
   void *start_addr;
+  // Copy of the datra:
   void *data;
+  // Size of the data region:
   size_t size;
 } s_mc_mem_region_t, *mc_mem_region_t;
 
@@ -43,14 +51,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 +80,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{
@@ -69,6 +94,8 @@ mc_snapshot_t SIMIX_pre_mc_snapshot(smx_simcall_t simcall);
 mc_snapshot_t MC_take_snapshot(int num_state);
 void MC_restore_snapshot(mc_snapshot_t);
 void MC_free_snapshot(mc_snapshot_t);
+void* mc_translate_address(uintptr_t addr, mc_snapshot_t snapshot);
+uintptr_t mc_untranslate_address(void* addr, mc_snapshot_t snapshot);
 
 extern xbt_dynar_t mc_checkpoint_ignore;
 
@@ -218,25 +245,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 +258,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 +270,6 @@ void print_comparison_times(void);
 //#define MC_DEBUG 1
 #define MC_VERBOSE 1
 
-
 /********************************** DPOR for safety property **************************************/
 
 typedef enum {
@@ -294,8 +301,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,94 +338,160 @@ 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 subprograms; // xbt_dict_t<origin as hexadecimal string, dw_frame_t>
+  xbt_dynar_t global_variables; // xbt_dynar_t<dw_variable_t>
+  xbt_dict_t types; // xbt_dict_t<origin as hexadecimal string, dw_type_t>
+  xbt_dict_t full_types_by_name; // xbt_dict_t<name, dw_type_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;
+extern mc_object_info_t mc_object_infos[2];
+extern size_t mc_object_infos_size;
+
+void MC_find_object_address(memory_map_t maps, mc_object_info_t result);
+void MC_post_process_types(mc_object_info_t info);
+
+// ***** Expressions
+
+/** \brief a DWARF expression with optional validity contraints */
+typedef struct s_mc_expression {
+  size_t size;
+  Dwarf_Op* ops;
+  // Optional validity:
+  void* lowpc, *highpc;
+} s_mc_expression_t, *mc_expression_t;
 
-typedef enum {
-  e_dw_loclist,
-  e_dw_register,
-  e_dw_bregister_op,
-  e_dw_lit,
-  e_dw_fbregister_op,
-  e_dw_piece,
-  e_dw_arithmetic,
-  e_dw_plus_uconst,
-  e_dw_compose,
-  e_dw_deref,
-  e_dw_uconstant,
-  e_dw_sconstant,
-  e_dw_unsupported
-} e_dw_location_type;
-
-typedef struct s_dw_location{
-  e_dw_location_type type;
-  union{
-    
-    xbt_dynar_t loclist;
-    
-    int reg;
-    
-    struct{
-      unsigned int reg;
-      int offset;
-    }breg_op;
-
-    unsigned int lit;
-
-    int fbreg_op;
-
-    int piece;
-
-    unsigned short int deref_size;
-
-    xbt_dynar_t compose;
-
-    char *arithmetic;
-
-    struct{
-      int bytes;
-      long unsigned int value;
-    }uconstant;
-
-    struct{
-      int bytes;
-      long signed int value;
-    }sconstant;
-
-    unsigned int plus_uconst;
-
-  }location;
-}s_dw_location_t, *dw_location_t;
-
-typedef struct s_dw_location_entry{
-  unsigned long lowpc;
-  unsigned long highpc;
-  dw_location_t location;
-}s_dw_location_entry_t, *dw_location_entry_t;
+/** A location list (list of location expressions) */
+typedef struct s_mc_location_list {
+  size_t size;
+  mc_expression_t locations;
+} s_mc_location_list_t, *mc_location_list_t;
+
+Dwarf_Off mc_dwarf_resolve_location(mc_expression_t expression, unw_cursor_t* c, void* frame_pointer_address, mc_snapshot_t snapshot);
+Dwarf_Off mc_dwarf_resolve_locations(mc_location_list_t locations, unw_cursor_t* c, void* frame_pointer_address, mc_snapshot_t snapshot);
+
+void mc_dwarf_expression_clear(mc_expression_t expression);
+void mc_dwarf_expression_init(mc_expression_t expression, size_t len, Dwarf_Op* ops);
+
+void mc_dwarf_location_list_clear(mc_location_list_t list);
+
+void mc_dwarf_location_list_init_from_expression(mc_location_list_t target, size_t len, Dwarf_Op* ops);
+void mc_dwarf_location_list_init(mc_location_list_t target, mc_object_info_t info, Dwarf_Die* die, Dwarf_Attribute* attr);
+
+// ***** Variables and functions
+
+struct s_dw_type{
+  e_dw_type_type 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 id */
+  xbt_dynar_t members; /* if DW_TAG_structure_type, DW_TAG_class_type, DW_TAG_union_type*/
+  int is_pointer_type;
+
+  // Location (for members) is either of:
+  struct s_mc_expression location;
+  int offset;
+
+  dw_type_t subtype; // DW_AT_type
+  dw_type_t full_type; // The same (but more complete) type
+};
+
+void* mc_member_resolve(const void* base, dw_type_t type, dw_type_t member, mc_snapshot_t snapshot);
+void* mc_member_snapshot_resolve(const void* base, dw_type_t type, dw_type_t member, mc_snapshot_t snapshot);
 
 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:
+  s_mc_location_list_t locations;
+  void* address;
+
+  size_t start_scope;
+
 }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;
+  s_mc_location_list_t frame_base;
+  xbt_dynar_t /* <dw_variable_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 mc_frame_free(dw_frame_t freme);
+
+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 **********************************/
+
+#define MC_EXPRESSION_STACK_SIZE 64
+
+#define MC_EXPRESSION_OK 0
+#define MC_EXPRESSION_E_UNSUPPORTED_OPERATION 1
+#define MC_EXPRESSION_E_STACK_OVERFLOW 2
+#define MC_EXPRESSION_E_STACK_UNDERFLOW 3
+#define MC_EXPRESSION_E_MISSING_STACK_CONTEXT 4
+#define MC_EXPRESSION_E_MISSING_FRAME_BASE 5
+
+typedef struct s_mc_expression_state {
+  uintptr_t stack[MC_EXPRESSION_STACK_SIZE];
+  size_t stack_size;
+
+  unw_cursor_t* cursor;
+  void* frame_base;
+  mc_snapshot_t snapshot;
+} s_mc_expression_state_t, *mc_expression_state_t;
+
+int mc_dwarf_execute_expression(size_t n, const Dwarf_Op* ops, mc_expression_state_t state);
+
+void* mc_find_frame_base(dw_frame_t frame, unw_cursor_t* unw_cursor);
 
 /********************************** Miscellaneous **********************************/
 
@@ -428,10 +499,49 @@ 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;
+  const char *src_host;
+  const char *dst_host;
+  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();
+void 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
 
index 1392a35..9fb5ad5 100644 (file)
@@ -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;
@@ -275,9 +279,9 @@ char *MC_request_to_string(smx_simcall_t req, int value)
   }
 
   if(args != NULL){
-    str = bprintf("[(%lu)%s (%s)] %s(%s) (%d)", req->issuer->pid , MSG_host_get_name(req->issuer->smx_host), req->issuer->name, type, args, req->call);
+    str = bprintf("[(%lu)%s (%s)] %s(%s)", req->issuer->pid , MSG_host_get_name(req->issuer->smx_host), req->issuer->name, type, args);
   }else{
-    str = bprintf("[(%lu)%s (%s)] %s (%d) ", req->issuer->pid , MSG_host_get_name(req->issuer->smx_host), req->issuer->name, type, req->call);
+    str = bprintf("[(%lu)%s (%s)] %s ", req->issuer->pid , MSG_host_get_name(req->issuer->smx_host), req->issuer->name, type);
   }
 
   xbt_free(args);
@@ -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 (file)
index 0000000..1ab9584
--- /dev/null
@@ -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 <stddef.h>
+#include <set>
+
+typedef std::set<const void*>*  mc_address_set_t;
+
+extern "C" {
+
+mc_address_set_t mc_address_set_new();
+void 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<const void*>();
+}
+
+void 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();
+}
+
+};
index d0cef47..64dcb1a 100644 (file)
@@ -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;
index fd2dfd2..7d4da0b 100644 (file)
@@ -598,6 +598,18 @@ void sg_config_init(int *argc, char **argv)
                      xbt_cfgelm_string, 1, 1, _mc_cfg_cb_property, NULL);
     xbt_cfg_setdefault_string(_sg_cfg_set, "model-check/property", "");
 
+    /* do communications 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, 1, 1, _mc_cfg_cb_comms_determinism, NULL);
+    xbt_cfg_setdefault_boolean(_sg_cfg_set, "model-check/communications_determinism", "no");
+
+    /* do send determinism model-checking */
+    xbt_cfg_register(&_sg_cfg_set, "model-check/send_determinism",
+                     "Enable/disable the detection of send-determinism in the communications schemes",
+                     xbt_cfgelm_boolean, 1, 1, _mc_cfg_cb_send_determinism, NULL);
+    xbt_cfg_setdefault_boolean(_sg_cfg_set, "model-check/send_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)",
@@ -610,6 +622,12 @@ void sg_config_init(int *argc, char **argv)
                      xbt_cfgelm_boolean, 1, 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 (exprimental)",
+                     xbt_cfgelm_boolean, 1, 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)",
index fc3f4b8..b6c5e60 100644 (file)
@@ -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)
index 5fccdc5..5362b82 100644 (file)
@@ -774,7 +774,7 @@ void smpi_mpi_wait(MPI_Request * request, MPI_Status * status)
   if ((*request)->action != NULL) { // this is not a detached send
     simcall_comm_wait((*request)->action, -1.0);
 #ifdef HAVE_MC
-  if(MC_is_active())
+  if(MC_is_active() && (*request)->action)
     (*request)->action->comm.dst_data = NULL; // dangling pointer : dst_data is freed with a wait, need to set it to NULL for system state comparison
 #endif
   }
index 46a46c8..37f8dd0 100644 (file)
@@ -102,6 +102,12 @@ void smpi_process_destroy(void)
  */
 void smpi_process_finalize(void)
 {
+#if 0
+  // wait for all pending asynchronous comms to finish
+  while (SIMIX_process_has_pending_comms(SIMIX_process_self())) {
+    simcall_process_sleep(0.01);
+  }
+#else
   int i;
   int size = smpi_comm_size(MPI_COMM_WORLD);
   int rank = smpi_comm_rank(MPI_COMM_WORLD);
@@ -133,7 +139,7 @@ void smpi_process_finalize(void)
     smpi_mpi_waitall( size-1, requests+1, MPI_STATUSES_IGNORE );
     free( requests );
   }
-
+#endif
 }
 
 /**
index 3731048..b32ec96 100644 (file)
@@ -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 <libunwind.h>
 #endif
 /* end of "useless" inclusions */
index 39cd21c..7258e6f 100644 (file)
@@ -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,18 @@ 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;
+  // Number of blocks in the heaps:
+  size_t heapsize1, heapsize2;
+  xbt_dynar_t to_ignore1, to_ignore2;
+  heap_area_t **equals_to1, **equals_to2;
+  dw_type_t **types1, **types2;
+};
+
+__thread struct s_mm_diff* mm_diff_info = NULL;
 
 /*********************************** Free functions ************************************/
 
@@ -242,7 +249,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 +259,132 @@ 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){
+/** Check whether two blocks are known to be matching
+ *
+ *  @param state  State used
+ *  @param b1     Block of state 1
+ *  @param b2     Block of state 2
+ *  @return       if the blocks are known to be matching
+ */
+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){
+/** Check whether two fragments are known to be matching
+ *
+ *  @param state  State used
+ *  @param b1     Block of state 1
+ *  @param f1     Fragment of state 1
+ *  @param b2     Block of state 2
+ *  @param f2     Fragment of state 2
+ *  @return       if the fragments are known to be matching
+ */
+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 - xbt_pagesize;
+  state->s_heap = (char *)mmalloc_get_current_heap() - STD_HEAP_SIZE - xbt_pagesize;
 
-  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; j<MAX_FRAGMENT_PER_BLOCK; j++){
-      equals_to1[i][j] = NULL;
-      types1[i][j] = NULL;
+      state->equals_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; j<MAX_FRAGMENT_PER_BLOCK; j++){
-      equals_to2[i][j] = NULL;
-      types2[i][j] = NULL;
+      state->equals_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 +393,42 @@ 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; j<MAX_FRAGMENT_PER_BLOCK;j++){
-      heap_area_free(equals_to1[i][j]);
-      equals_to1[i][j] = NULL;
-      heap_area_free(equals_to2[i][j]);
-      equals_to2[i][j] = NULL;
-      xbt_free(types1[i][j]);
-      types1[i][j] = NULL;
-      xbt_free(types2[i][j]);
-      types2[i][j] = NULL;
+      heap_area_free(state->equals_to1[i][j]);
+      state->equals_to1[i][j] = NULL;
+      heap_area_free(state->equals_to2[i][j]);
+      state-> equals_to2[i][j] = NULL;
+      state->types1[i][j] = NULL;
+      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(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2, xbt_mheap_t heap1, xbt_mheap_t heap2){
+
+  struct s_mm_diff *state = mm_diff_info;
 
   if(heap1 == NULL && heap2 == NULL){
     XBT_DEBUG("Malloc descriptors null");
@@ -428,27 +448,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 +478,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, snapshot1, snapshot2, NULL, 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 +501,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, snapshot1, snapshot2, NULL, 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 +538,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, snapshot1, snapshot2, NULL, NULL, 0);
 
             if(res_compare !=  1)
               equal = 1;
@@ -558,25 +578,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, snapshot2, snapshot2, NULL, NULL, 0);
             
             if(res_compare != 1){
               equal = 1;
@@ -593,9 +613,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 +632,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 +647,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 +669,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 +689,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 +711,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 +720,31 @@ 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){
+/**
+ *
+ * @param state
+ * @param real_area1     Process address for state 1
+ * @param real_area2     Process address for state 2
+ * @param area1          Snapshot address for state 1
+ * @param area2          Snapshot address for state 2
+ * @param snapshot1      Snapshot of state 1
+ * @param snapshot2      Snapshot of state 2
+ * @param previous
+ * @param size
+ * @param check_ignore
+ */
+static int compare_heap_area_without_type(struct s_mm_diff *state, void *real_area1, void *real_area2, void *area1, void *area2, mc_snapshot_t snapshot1, mc_snapshot_t snapshot2, xbt_dynar_t previous, 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<size){
 
     if(check_ignore > 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 +766,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, snapshot1, snapshot2, previous, NULL, 0);
         if(res_compare == 1){
           return res_compare;
         }
@@ -754,103 +788,113 @@ 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, 
+/**
+ *
+ * @param state
+ * @param real_area1     Process address for state 1
+ * @param real_area2     Process address for state 2
+ * @param area1          Snapshot address for state 1
+ * @param area2          Snapshot address for state 2
+ * @param snapshot1      Snapshot of state 1
+ * @param snapshot2      Snapshot of state 2
+ * @param previous
+ * @param type_id
+ * @param area_size      either a byte_size or an elements_count (?)
+ * @param check_ignore
+ * @param pointer_level
+ * @return               0 (same), 1 (different), -1 (unknown)
+ */
+static int compare_heap_area_with_type(struct s_mm_diff *state, void *real_area1, void *real_area2, void *area1, void *area2,
+                                       mc_snapshot_t snapshot1, mc_snapshot_t snapshot2,
+                                       xbt_dynar_t previous, dw_type_t type,
                                        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 subtype, subsubtype;
-  int res, elm_size, i, switch_types = 0;
+  int res, elm_size, i;
   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_unspecified_type:
+    return 1;
+
+  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, snapshot1, snapshot2, previous, type->subtype, 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 = 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 */
-        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));
-          switch_types = 1;
-        }
-      }
-      elm_size = subtype->size;
+    case DW_TAG_unspecified_type:
+      return 1;
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    case DW_TAG_pointer_type:
+    case DW_TAG_reference_type:
+    case DW_TAG_rvalue_reference_type:
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:
+      if(subtype->full_type)
+        subtype = subtype->full_type;
+      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));
-          switch_types = 1;
-        }
-      }
-      elm_size = subsubtype->size;
+    // 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->full_type)
+        subsubtype = subsubtype->full_type;
+      elm_size = subsubtype->byte_size;
       break;
     default : 
       return 0;
       break;
     }
-    for(i=0; i<type->size; i++){ 
-      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);
-      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);
+    for(i=0; i<type->element_count; i++){
+      // TODO, add support for variable stride (DW_AT_byte_stride)
+      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), snapshot1, snapshot2, previous, type->subtype, 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_reference_type:
+  case DW_TAG_rvalue_reference_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);;
@@ -860,8 +904,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, snapshot1, snapshot2, previous, type->subtype, pointer_level);
           else
             res =  (addr_pointed1 != addr_pointed2);
           if(res == 1)
@@ -870,30 +914,21 @@ 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, snapshot1, snapshot2, previous, type->subtype, 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);
-      }else{
-        type = xbt_dict_get_or_null(other_types, get_type_description(other_types, 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(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); 
-          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); 
+  case DW_TAG_structure_type:
+  case DW_TAG_class_type:
+    if(type->full_type)
+      type = type->full_type;
+    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++){
+          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), snapshot1, snapshot2, previous, type, -1, check_ignore, 0);
           if(res == 1)
             return res;
         }
@@ -902,22 +937,21 @@ static int compare_heap_area_with_type(void *real_area1, void *real_area2, void
       }
     }else{
       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);
-        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);  
+      xbt_dynar_foreach(type->members, cursor, member){
+        // TODO, optimize this? (for the offset case)
+        char* real_member1 = mc_member_resolve(real_area1, type, member, snapshot1);
+        char* real_member2 = mc_member_resolve(real_area2, type, member, snapshot2);
+        char* member1 = mc_translate_address((uintptr_t)real_member1, snapshot1);
+        char* member2 = mc_translate_address((uintptr_t)real_member2, snapshot2);
+        res = compare_heap_area_with_type(state, real_member1, real_member2, member1, member2, snapshot1, snapshot2, previous, member->subtype, -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, snapshot1, snapshot2, previous, type->byte_size, check_ignore);
     break;
   default:
     break;
@@ -927,46 +961,48 @@ 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);
-  if(type == NULL){
-    type = xbt_dict_get_or_null(other_types, type_id);
-    *switch_type = 1;
-  }
-  char* type_desc;
+/** Infer the type of a part of the block from the type of the block
+ *
+ * TODO, handle DW_TAG_array_type as well as arrays of the object ((*p)[5], p[5])
+ *
+ * TODO, handle subfields ((*p).bar.foo, (*p)[5].bar…)
+ *
+ * @param  type_id            DWARF type ID of the root address
+ * @param  area_size
+ * @return                    DWARF type ID for given offset
+ */
+static dw_type_t get_offset_type(void* real_base_address, dw_type_t type, int offset, int area_size, mc_snapshot_t snapshot){
+
+  // Beginning of the block, the infered variable type if the type of the block:
+  if(offset==0)
+    return type;
+
   switch(type->type){
-  case e_dw_structure_type :
-    if(type->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);
-        }else{
-          type = xbt_dict_get_or_null(other_types, get_type_description(other_types, 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);
-        }else{
-          type = xbt_dict_get_or_null(all_types, get_type_description(other_types, type->name));
-          *switch_type = 0;
-        }
-      }
+  case DW_TAG_structure_type :
+  case DW_TAG_class_type:
+    if(type->full_type)
+      type = type->full_type;
     
-    }
-    if(area_size != -1 && type->size != area_size){
-      if(area_size>type->size && area_size%type->size == 0)
-        return type_id;
+    if(area_size != -1 && type->byte_size != area_size){
+      if(area_size>type->byte_size && area_size%type->byte_size == 0)
+        return type;
       else
         return NULL;
     }else{
       unsigned int cursor = 0;
       dw_type_t member;
       xbt_dynar_foreach(type->members, cursor, member){ 
-        if(member->offset == offset)
-          return member->dw_type_id;
+
+        if(!member->location.size) {
+          // We have the offset, use it directly (shortcut):
+          if(member->offset == offset)
+            return member->subtype;
+        } else {
+          char* real_member = mc_member_resolve(real_base_address, type, member, snapshot);
+          if(real_member - (char*)real_base_address == offset)
+            return member->subtype;
+        }
+
       }
       return NULL;
     }
@@ -978,7 +1014,20 @@ 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){
+/**
+ *
+ * @param area1          Process address for state 1
+ * @param area2          Process address for state 2
+ * @param snapshot1      Snapshot of state 1
+ * @param snapshot2      Snapshot of state 2
+ * @param previous       Pairs of blocks already compared on the current path (or NULL)
+ * @param type_id        Type of variable
+ * @param pointer_level
+ * @return 0 (same), 1 (different), -1
+ */
+int compare_heap_area(void *area1, void* area2, mc_snapshot_t snapshot1, mc_snapshot_t snapshot2, xbt_dynar_t previous, dw_type_t type, int pointer_level){
+
+  struct s_mm_diff* state = mm_diff_info;
 
   int res_compare;
   ssize_t block1, frag1, block2, frag2;
@@ -987,13 +1036,10 @@ 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;
-  char *new_type_id1 = NULL, *new_type_id2 = NULL;
-  int switch_type = 0;
+  dw_type_t new_type1 = NULL, new_type2 = NULL;
 
   int match_pairs = 0;
 
@@ -1002,64 +1048,70 @@ 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;
+  // Get block number:
+  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 either block is a stack block:
   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 either block is not in the expected area of memory:
+  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));
+  // Snapshot address of the block:
+  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));
+  // Process address of the block:
+  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);
-        else
-          type = xbt_dict_get_or_null(other_types, get_type_description(other_types, type->name));
-      }else{
-        type = xbt_dict_get_or_null(all_types, type->dw_type_id);
-      }
-    }
-    if((type->type == e_dw_pointer_type) || ((type->type == e_dw_base_type) && (!strcmp(type->name, "char"))))
+  if(type){
+
+    if(type->full_type)
+      type = type->full_type;
+
+    // This assume that for "boring" types (volatile ...) byte_size is absent:
+    while(type->byte_size == 0 && type->subtype!=NULL)
+      type = type->subtype;
+
+    // Find type_size:
+    if((type->type == 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)){
+    // TODO, lookup variable type from block type as done for fragmented blocks
+
+    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 +1119,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 +1146,28 @@ 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);
+    // Remember (basic) type inference.
+    // The current data structure only allows us to do this for the whole block.
+    if (type != NULL && area1==real_addr_block1) {
+      xbt_free(state->types1[block1][0]);
+      state->types1[block1][0] = type;
+    }
+    if (type != NULL && area2==real_addr_block2) {
+      xbt_free(state->types2[block2][0]);
+      state->types2[block2][0] = type;
     }
 
     if(size <= 0){
       if(match_pairs){
-        match_equals(previous);
+        match_equals(state, previous);
         xbt_dynar_free(&previous);
       }
       return 0;
@@ -1121,51 +1179,57 @@ 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;
+    // Fragment number:
+    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));
+    // Snapshot address of the fragment:
+    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));
+    // Process address of the fragment:
+    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));
 
+    // Check the size of the fragments against the size of the 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)){
+    // Check if the blocks are already matched together:
+    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]){
+    // Compare the size of both fragments:
+    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,58 +1241,62 @@ int compare_heap_area(void *area1, void* area2, xbt_dynar_t previous, xbt_dict_t
       }
     }
       
-    size = heapinfo1[block1].busy_frag.frag_size[frag1];
+    // Size of the fragment:
+    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);
+    // Remember (basic) type inference.
+    // The current data structure only allows us to do this for the whole block.
+    if(type != NULL && area1==real_addr_frag1){
+      state->types1[block1][frag1] = type;
     }
+    if(type != NULL && area2==real_addr_frag2) {
+      state->types2[block2][frag2] = type;
+    }
+
+    // The type of the variable is already known:
+    if(type) {
+      new_type1 = type;
+      new_type2 = type;
+    }
+
+    // Type inference from the block type.
+    else if(state->types1[block1][frag1] != NULL || state->types2[block2][frag2] != NULL) {
 
-    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_type1 = get_offset_type(real_addr_frag1, state->types1[block1][frag1], offset1, size, snapshot1);
+        new_type2 = get_offset_type(real_addr_frag2, state->types2[block2][frag2], offset1, size, snapshot2);
+      }else if(state->types1[block1][frag1] != NULL){
+        new_type1 = get_offset_type(real_addr_frag1, state->types1[block1][frag1], offset1, size, snapshot1);
+        new_type2 = get_offset_type(real_addr_frag2, state->types1[block1][frag1], offset2, size, snapshot2);
+      }else if(state->types2[block2][frag2] != NULL){
+        new_type1 = get_offset_type(real_addr_frag1, state->types2[block2][frag2], offset1, size, snapshot1);
+        new_type2 = get_offset_type(real_addr_frag2, state->types2[block2][frag2], offset2, size, snapshot2);
       }else{
         if(match_pairs){
-          match_equals(previous);
+          match_equals(state, previous);
           xbt_dynar_free(&previous);
         }
         return -1;
       }   
 
-      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;
-        }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;
-        }
+      if(new_type1 !=  NULL && new_type2 !=  NULL && new_type1!=new_type2){
+
+          type = new_type1;
+          while(type->byte_size == 0 && type->subtype != NULL)
+            type = type->subtype;
+          new_size1 = type->byte_size;
+
+          type = new_type2;
+          while(type->byte_size == 0 && type->subtype != NULL)
+            type = type->subtype;
+          new_size2 = type->byte_size;
+
       }else{
         if(match_pairs){
-          match_equals(previous);
+          match_equals(state, previous);
           xbt_dynar_free(&previous);
         }
         return -1;
@@ -1239,14 +1307,14 @@ int compare_heap_area(void *area1, void* area2, xbt_dynar_t previous, xbt_dict_t
     area2_to_compare = (char *)addr_frag2 + offset2;
     
     if(new_size1 > 0 && new_size1 == new_size2){
-      type_id = new_type_id1;
+      type = new_type1;
       size = new_size1;
     }
 
     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 +1323,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{
 
@@ -1275,30 +1343,19 @@ 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);
-    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);
-    if(res_compare == 1){
-      if(match_pairs)
-        xbt_dynar_free(&previous);
-      return res_compare;
-    }
+  if(type){
+    res_compare = compare_heap_area_with_type(state, area1, area2, area1_to_compare, area2_to_compare, snapshot1, snapshot2, previous, type, size, check_ignore, pointer_level);
   }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);
-    else
-      res_compare = compare_heap_area_without_type(area1, area2, area1_to_compare, area2_to_compare, previous, all_types, other_types, size, check_ignore);
-    if(res_compare == 1){
-      if(match_pairs)
-        xbt_dynar_free(&previous);
-      return res_compare;
-    }
+    res_compare = compare_heap_area_without_type(state, area1, area2, area1_to_compare, area2_to_compare, snapshot1, snapshot2, previous, size, check_ignore);
+  }
+  if(res_compare == 1){
+    if(match_pairs)
+      xbt_dynar_free(&previous);
+    return res_compare;
   }
 
   if(match_pairs){
-    match_equals(previous);
+    match_equals(state, previous);
     xbt_dynar_free(&previous);
   }
 
@@ -1308,20 +1365,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 +1394,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 +1417,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 +1433,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 - xbt_pagesize;
+  state->s_heap = (char *)mmalloc_get_current_heap() - STD_HEAP_SIZE - xbt_pagesize;
 
-  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 +1456,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 +1493,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 +1504,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 +1523,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 ++;
             }
index ece1e25..9ebf1f7 100644 (file)
@@ -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;
index d6fd63c..5844207 100644 (file)
@@ -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);
diff --git a/testsuite/mc/CMakeLists.txt b/testsuite/mc/CMakeLists.txt
new file mode 100644 (file)
index 0000000..3970c88
--- /dev/null
@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION 2.6)
+
+if(HAVE_MC)
+  set(EXECUTABLE_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}")
+  add_executable(dwarf dwarf.c)
+  target_link_libraries(dwarf simgrid)
+
+  add_executable(dwarf-expression dwarf_expression.c)
+  target_link_libraries(dwarf-expression simgrid)
+endif()
diff --git a/testsuite/mc/dwarf.c b/testsuite/mc/dwarf.c
new file mode 100644 (file)
index 0000000..fc85de4
--- /dev/null
@@ -0,0 +1,142 @@
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+#include <string.h>
+#include <assert.h>
+
+#include <xbt.h>
+#include <mc/mc.h>
+
+#include "../../src/include/mc/datatypes.h"
+#include "../../src/mc/mc_private.h"
+
+int test_some_array[4][5][6];
+struct some_struct { int first; int second[4][5]; } test_some_struct;
+
+static dw_type_t find_type_by_name(mc_object_info_t info, const char* name) {
+  xbt_dict_cursor_t cursor = NULL;
+  char *key;
+  dw_type_t type;
+  xbt_dict_foreach(info->types, cursor, key, type) {
+    if(!strcmp(name, type->name))
+      return type;
+  }
+
+  return NULL;
+}
+
+static dw_variable_t find_global_variable_by_name(mc_object_info_t info, const char* name) {
+  unsigned int cursor = 0;
+  dw_variable_t variable;
+  xbt_dynar_foreach(info->global_variables, cursor, variable){
+    if(!strcmp(name, variable->name))
+      return variable;
+  }
+
+  return NULL;
+}
+
+static dw_frame_t find_function_by_name(mc_object_info_t info, const char* name) {
+  xbt_dict_cursor_t cursor = 0;
+  dw_frame_t subprogram;
+  char* key;
+  xbt_dict_foreach(info->subprograms, cursor, key, subprogram){
+    if(!strcmp(name, subprogram->name))
+      return subprogram;
+  }
+
+  return NULL;
+}
+
+static dw_variable_t find_local_variable(dw_frame_t frame, const char* argument_name) {
+  unsigned int cursor = 0;
+  dw_variable_t variable;
+  xbt_dynar_foreach(frame->variables, cursor, variable){
+    if(!strcmp(argument_name, variable->name))
+      return variable;
+  }
+
+  return NULL;
+}
+
+static void test_local_variable(mc_object_info_t info, const char* function, const char* variable, void* address, unw_cursor_t* cursor) {
+  dw_frame_t subprogram = find_function_by_name(info, function);
+  assert(subprogram);
+  // TODO, Lookup frame by IP and test against name instead
+
+  dw_variable_t var = find_local_variable(subprogram, variable);
+  assert(var);
+
+  void* frame_base = mc_find_frame_base(subprogram, cursor);
+  xbt_assert((void*)mc_dwarf_resolve_locations(&var->locations, cursor, frame_base, NULL) == address,
+    "Bad resolution of local variable %s of %s", variable, function);
+
+}
+
+static dw_variable_t test_global_variable(mc_object_info_t info, const char* name, void* address, long byte_size) {
+  dw_variable_t variable = find_global_variable_by_name(info, name);
+  xbt_assert(variable, "Global variable %s was not found", name);
+  xbt_assert(!strcmp(variable->name, name), "Name mismatch for %s", name);
+  xbt_assert(variable->global, "Variable %s is not global", name);
+  xbt_assert(variable->address == address,
+      "Address mismatch for %s : %p expected but %p found", name, address, variable->address);
+
+  dw_type_t type = xbt_dict_get_or_null(mc_binary_info->types, variable->type_origin);
+  xbt_assert(type!=NULL, "Missing type for %s", name);
+  xbt_assert(type->byte_size = byte_size, "Byte size mismatch for %s", name);
+  return variable;
+}
+
+static dw_type_t find_member(mc_object_info_t info, const char* name, dw_type_t type) {
+  unsigned int cursor = 0;
+  dw_type_t member;
+  xbt_dynar_foreach(type->members, cursor, member){
+    if(!strcmp(name,member->name))
+      return member;
+  }
+  return NULL;
+}
+
+int some_local_variable = 0;
+
+typedef struct foo {int i;} s_foo;
+
+static void test_type_by_name(s_foo my_foo) {
+  assert(xbt_dict_get_or_null(mc_binary_info->full_types_by_name, "struct foo"));
+}
+
+int main(int argc, char** argv) {
+
+  // xbt_init(&argc, argv);
+  SIMIX_global_init(&argc, argv);
+  MC_memory_init();
+  MC_init();
+
+  dw_variable_t var;
+  dw_type_t type;
+
+  var = test_global_variable(mc_binary_info, "some_local_variable", &some_local_variable, sizeof(int));
+
+  var = test_global_variable(mc_binary_info, "test_some_array", &test_some_array, sizeof(test_some_array));
+  type = xbt_dict_get_or_null(mc_binary_info->types, var->type_origin);
+  xbt_assert(type->element_count == 6*5*4, "element_count mismatch in test_some_array : %i / %i", type->element_count, 6*5*4);
+
+  var = test_global_variable(mc_binary_info, "test_some_struct", &test_some_struct, sizeof(test_some_struct));
+  type = xbt_dict_get_or_null(mc_binary_info->types, var->type_origin);
+  assert(find_member(mc_binary_info, "first", type)->offset == 0);
+  assert(find_member(mc_binary_info, "second", type)->offset
+      == ((const char*)&test_some_struct.second) - (const char*)&test_some_struct);
+
+  unw_context_t context;
+  unw_cursor_t cursor;
+  unw_getcontext(&context);
+  unw_init_local(&cursor, &context);
+
+  test_local_variable(mc_binary_info, "main", "argc", &argc, &cursor);
+
+  s_foo my_foo;
+  test_type_by_name(my_foo);
+
+  _exit(0);
+}
diff --git a/testsuite/mc/dwarf_expression.c b/testsuite/mc/dwarf_expression.c
new file mode 100644 (file)
index 0000000..98ee29a
--- /dev/null
@@ -0,0 +1,141 @@
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "../src/mc/mc_private.h"
+
+static
+uintptr_t eval_binary_operation(mc_expression_state_t state, int op, uintptr_t a, uintptr_t b) {
+  state->stack_size = 0;
+
+  Dwarf_Op ops[15];
+  ops[0].atom = DW_OP_addr;
+  ops[0].number = a;
+  ops[1].atom = DW_OP_addr;
+  ops[1].number = b;
+  ops[2].atom = op;
+
+  assert(mc_dwarf_execute_expression(3, ops, state) == MC_EXPRESSION_OK);
+  assert(state->stack_size==1);
+  return state->stack[state->stack_size - 1];
+}
+
+static
+void basic_test(mc_expression_state_t state) {
+  Dwarf_Op ops[60];
+
+  uintptr_t a = rand();
+  uintptr_t b = rand();
+
+  ops[0].atom = DW_OP_drop;
+  assert(mc_dwarf_execute_expression(1, ops, state) == MC_EXPRESSION_E_STACK_UNDERFLOW);
+
+  ops[0].atom = DW_OP_lit21;
+  assert(mc_dwarf_execute_expression(1, ops, state) == MC_EXPRESSION_OK);
+  assert(state->stack_size==1);
+  assert(state->stack[state->stack_size-1]==21);
+
+  ops[0].atom = DW_OP_addr;
+  ops[0].number = a;
+  assert(mc_dwarf_execute_expression(1, ops, state) == MC_EXPRESSION_OK);
+  assert(state->stack_size==2);
+  assert(state->stack[state->stack_size-1] == a);
+
+  ops[0].atom = DW_OP_drop;
+  ops[1].atom = DW_OP_drop;
+  assert(mc_dwarf_execute_expression(2, ops, state) == MC_EXPRESSION_OK);
+  assert(state->stack_size==0);
+
+  ops[0].atom = DW_OP_lit21;
+  ops[1].atom = DW_OP_plus_uconst;
+  ops[1].number = a;
+  assert(mc_dwarf_execute_expression(2, ops, state) == MC_EXPRESSION_OK);
+  assert(state->stack_size==1);
+  assert(state->stack[state->stack_size-1]== a + 21);
+
+  state->stack_size = 0;
+  ops[0].atom = DW_OP_addr;
+  ops[0].number = a;
+  ops[1].atom = DW_OP_dup;
+  ops[2].atom = DW_OP_plus;
+  assert(mc_dwarf_execute_expression(3, ops, state) == MC_EXPRESSION_OK);
+  assert(state->stack_size==1);
+  assert(state->stack[state->stack_size-1]== a + a);
+
+  state->stack_size = 0;
+  ops[0].atom = DW_OP_addr;
+  ops[0].number = a;
+  ops[1].atom = DW_OP_addr;
+  ops[1].number = b;
+  ops[2].atom = DW_OP_over;
+  assert(mc_dwarf_execute_expression(3, ops, state) == MC_EXPRESSION_OK);
+  assert(state->stack_size==3);
+  assert(state->stack[state->stack_size-1]== a);
+  assert(state->stack[state->stack_size-2]== b);
+  assert(state->stack[state->stack_size-3]== a);
+
+  state->stack_size = 0;
+  ops[0].atom = DW_OP_addr;
+  ops[0].number = a;
+  ops[1].atom = DW_OP_addr;
+  ops[1].number = b;
+  ops[2].atom = DW_OP_swap;
+  assert(mc_dwarf_execute_expression(3, ops, state) == MC_EXPRESSION_OK);
+  assert(state->stack_size=2);
+  assert(state->stack[state->stack_size-1]== a);
+  assert(state->stack[state->stack_size-2]== b);
+}
+
+static
+void test_deref(mc_expression_state_t state) {
+  uintptr_t foo = 42;
+
+  Dwarf_Op ops[60];
+  ops[0].atom = DW_OP_addr;
+  ops[0].number = (Dwarf_Word) &foo;
+  ops[1].atom = DW_OP_deref;
+  state->stack_size = 0;
+
+  assert(mc_dwarf_execute_expression(2, ops, state) == MC_EXPRESSION_OK);
+  assert(state->stack_size==1);
+  assert(state->stack[state->stack_size-1] == foo);
+}
+
+int main(int argc, char** argv) {
+  s_mc_expression_state_t state;
+  memset(&state, 0, sizeof(s_mc_expression_state_t));
+
+  basic_test(&state);
+
+  for(int i=0; i!=100; ++i) {
+    uintptr_t a = rand();
+    uintptr_t b = rand();
+    assert(eval_binary_operation(&state, DW_OP_plus, a, b) == (a + b));
+  }
+
+  for(int i=0; i!=100; ++i) {
+    uintptr_t a = rand();
+    uintptr_t b = rand();
+    assert(eval_binary_operation(&state, DW_OP_or, a, b) == (a | b));
+  }
+
+  for(int i=0; i!=100; ++i) {
+    uintptr_t a = rand();
+    uintptr_t b = rand();
+    assert(eval_binary_operation(&state, DW_OP_and, a, b) == (a & b));
+  }
+
+  for(int i=0; i!=100; ++i) {
+    uintptr_t a = rand();
+    uintptr_t b = rand();
+    assert(eval_binary_operation(&state, DW_OP_xor, a, b) == (a ^ b));
+  }
+
+  test_deref(&state);
+
+  return 0;
+}