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()
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")
src/mc/mc_compare.c
src/mc/mc_dpor.c
src/mc/mc_global.c
+ src/mc/mc_dwarf.c
src/mc/mc_liveness.c
src/mc/mc_memory.c
src/mc/mc_private.h
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
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
# (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)
--- /dev/null
+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)
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)
$ ${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
$ ${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
--- /dev/null
+#!/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
#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
#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
/* 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'. */
void mmalloc_set_current_heap(xbt_mheap_t new_heap);
xbt_mheap_t mmalloc_get_current_heap(void);
-int mmalloc_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dict_t all_types, xbt_dict_t other_types);
+int mmalloc_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2, mc_object_info_t info, mc_object_info_t other_info);
int mmalloc_linear_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2);
int init_heap_information(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dynar_t to_ignore1, xbt_dynar_t to_ignore2);
-int compare_heap_area(void *area1, void* area2, xbt_dynar_t previous, xbt_dict_t all_types, xbt_dict_t other_types, char *type, int pointer_level);
+int compare_heap_area(void *area1, void* area2, xbt_dynar_t previous, mc_object_info_t info, mc_object_info_t other_info, char *type, int pointer_level);
void reset_heap_information(void);
-int get_pointed_area_size(void *area, int heap);
size_t mmalloc_get_bytes_used(xbt_mheap_t);
ssize_t mmalloc_get_busy_size(xbt_mheap_t, void *ptr);
#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 **********************************/
void heap_ignore_region_free(mc_heap_ignore_region_t r);
void heap_ignore_region_free_voidp(void *r);
+/************ Object info *************/
+
+typedef struct s_mc_object_info s_mc_object_info_t, *mc_object_info_t;
+
/************ DWARF structures *************/
-typedef enum{
- e_dw_base_type = 0,
- e_dw_enumeration_type,
- e_dw_enumerator,
- e_dw_typedef,
- e_dw_const_type,
- e_dw_array_type,
- e_dw_pointer_type,
- e_dw_structure_type,
- e_dw_union_type,
- e_dw_subroutine_type,
- e_dw_volatile_type
-}e_dw_type_type;
-
-typedef struct s_dw_type{
+typedef int e_dw_type_type;
+
+typedef struct s_dw_type s_dw_type_t, *dw_type_t;
+
+struct s_dw_type{
e_dw_type_type type;
- void *id;
- char *name;
- int size;
- char *dw_type_id;
- xbt_dynar_t members; /* if DW_TAG_structure_type */
+ void *id; /* Offset in the section (in hexadecimal form) */
+ char *name; /* Name of the type */
+ int byte_size; /* Size in bytes */
+ int element_count; /* Number of elements for array type */
+ char *dw_type_id; /* DW_AT_type */
+ xbt_dynar_t members; /* if DW_TAG_structure_type, DW_TAG_union_type*/
int is_pointer_type;
int offset;
-}s_dw_type_t, *dw_type_t;
+ dw_type_t subtype;
+ dw_type_t other_object_same_type; // The same (but more complete) type in the other object.
+};
-char* get_type_description(xbt_dict_t types, char *type_name);
+char* get_type_description(mc_object_info_t info, char *type_name);
SG_END_DECL()
#endif /* _MC_MC_H */
extern int _sg_mc_checkpoint;
extern char* _sg_mc_property_file;
extern int _sg_mc_timeout;
+extern int _sg_mc_hash;
extern int _sg_mc_max_depth;
extern int _sg_mc_visited;
extern char* _sg_mc_dot_output_file;
+extern int _sg_mc_comms_determinism;
extern xbt_dynar_t mc_heap_comparison_ignore;
extern xbt_dynar_t stacks_areas;
void _mc_cfg_cb_checkpoint(const char *name, int pos);
void _mc_cfg_cb_property(const char *name, int pos);
void _mc_cfg_cb_timeout(const char *name, int pos);
+void _mc_cfg_cb_hash(const char *name, int pos);
void _mc_cfg_cb_max_depth(const char *name, int pos);
void _mc_cfg_cb_visited(const char *name, int pos);
void _mc_cfg_cb_dot_output(const char *name, int pos);
+void _mc_cfg_cb_comms_determinism(const char *name, int pos);
XBT_PUBLIC(void) MC_do_the_modelcheck_for_real(void);
/* 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 **************************************/
/*****************************************************************************************/
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);
}
}
static void local_variable_free(local_variable_t v){
xbt_free(v->frame);
xbt_free(v->name);
- xbt_free(v->type);
xbt_free(v);
}
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);
static void MC_get_memory_regions(mc_snapshot_t snapshot){
- FILE *fp;
- char *line = NULL;
- ssize_t read;
- size_t n = 0;
-
- char *lfields[6] = {0}, *tok;
- void *start_addr, *start_addr1, *end_addr;
- size_t size;
- int i;
-
- fp = fopen("/proc/self/maps", "r");
-
- xbt_assert(fp,
- "Cannot open /proc/self/maps to investigate the memory map of the process. Please report this bug.");
-
- setbuf(fp, NULL);
-
- while((read = xbt_getline(&line, &n, fp)) != -1){
-
- /* Wipeout the new line character */
- line[read - 1] = '\0';
-
- /* Tokenize the line using spaces as delimiters and store each token */
- lfields[0] = strtok(line, " ");
-
- for (i = 1; i < 6 && lfields[i - 1] != NULL; i++) {
- lfields[i] = strtok(NULL, " ");
- }
-
- /* First get the permissions flags, need write permission */
- if(lfields[1][1] == 'w'){
-
- /* Get the start address of the map */
- tok = strtok(lfields[0], "-");
- start_addr = (void *)strtoul(tok, NULL, 16);
-
- if(start_addr == std_heap){ /* Std_heap ? */
- tok = strtok(NULL, "-");
- end_addr = (void *)strtoul(tok, NULL, 16);
- MC_snapshot_add_region(snapshot, 0, start_addr, (char*)end_addr - (char*)start_addr);
- snapshot->heap_bytes_used = mmalloc_get_bytes_used(std_heap);
- }else{ /* map name == libsimgrid || binary_name ? */
- if(lfields[5] != NULL){
- if(!memcmp(basename(lfields[5]), "libsimgrid", 10)){
- tok = strtok(NULL, "-");
- end_addr = (void *)strtoul(tok, NULL, 16);
- size = (char*)end_addr - (char*)start_addr;
- /* BSS and data segments may be separated according to the OS */
- if((read = xbt_getline(&line, &n, fp)) != -1){
- line[read - 1] = '\0';
- lfields[0] = strtok(line, " ");
- for (i = 1; i < 6 && lfields[i - 1] != NULL; i++) {
- lfields[i] = strtok(NULL, " ");
- }
- if(lfields[1][1] == 'w' && lfields[5] == NULL){
- tok = strtok(lfields[0], "-");
- start_addr1 = (void *)strtoul(tok, NULL, 16);
- tok = strtok(NULL, "-");
- size += (char *)(void *)strtoul(tok, NULL, 16) - (char*)start_addr1;
- }
- }
- MC_snapshot_add_region(snapshot, 1, start_addr, size);
- }else if(!memcmp(basename(lfields[5]), basename(xbt_binary_name), strlen(basename(xbt_binary_name)))){
- tok = strtok(NULL, "-");
- end_addr = (void *)strtoul(tok, NULL, 16);
- size = (char*)end_addr - (char*)start_addr;
- /* BSS and data segments may be separated according to the OS */
- if((read = xbt_getline(&line, &n, fp)) != -1){
- line[read - 1] = '\0';
- lfields[0] = strtok(line, " ");
- for (i = 1; i < 6 && lfields[i - 1] != NULL; i++) {
- lfields[i] = strtok(NULL, " ");
- }
- tok = strtok(lfields[0], "-");
- start_addr1 = (void *)strtoul(tok, NULL, 16);
- if(lfields[1][1] == 'w' && lfields[5] == NULL){
- if(start_addr1 == std_heap){ /* Std_heap ? */
- tok = strtok(NULL, "-");
- end_addr = (void *)strtoul(tok, NULL, 16);
- MC_snapshot_add_region(snapshot, 0, start_addr1, (char*)end_addr - (char*)start_addr1);
- snapshot->heap_bytes_used = mmalloc_get_bytes_used(std_heap);
- }else if(start_addr1 != raw_heap){
- tok = strtok(NULL, "-");
- size += (char *)(void *)strtoul(tok, NULL, 16) - (char *)start_addr1;
- }
- }
- }
- MC_snapshot_add_region(snapshot, 2, start_addr, size);
- }else if (!memcmp(lfields[5], "[stack]", 7)){
- maestro_stack_start = start_addr;
- tok = strtok(NULL, "-");
- maestro_stack_end = (void *)strtoul(tok, NULL, 16);
- }
- }
- }
- }
-
- }
-
- free(line);
- fclose(fp);
+ void* start_heap = ((xbt_mheap_t)std_heap)->base;
+ void* end_heap = ((xbt_mheap_t)std_heap)->breakval;
+ MC_snapshot_add_region(snapshot, 0, start_heap, (char*) end_heap - (char*) start_heap);
+ snapshot->heap_bytes_used = mmalloc_get_bytes_used(std_heap);
+ MC_snapshot_add_region(snapshot, 1, mc_libsimgrid_info->start_rw, mc_libsimgrid_info->end_rw - mc_libsimgrid_info->start_rw);
+ MC_snapshot_add_region(snapshot, 2, mc_binary_info->start_rw, mc_binary_info->end_rw - mc_binary_info->start_rw);
}
+/** @brief Finds the range of the different memory segments and binary paths */
void MC_init_memory_map_info(){
unsigned int i = 0;
s_map_region_t reg;
memory_map_t maps = MC_get_memory_map();
+ maestro_stack_start = NULL;
+ maestro_stack_end = NULL;
+ libsimgrid_path = NULL;
+
while (i < maps->mapsize) {
reg = maps->regions[i];
- if ((reg.prot & PROT_WRITE)){
- if (maps->regions[i].pathname != NULL){
- if (!memcmp(basename(maps->regions[i].pathname), "libsimgrid", 10)){
- start_data_libsimgrid = reg.start_addr;
- i++;
- reg = maps->regions[i];
- if(reg.pathname == NULL && (reg.prot & PROT_WRITE) && i < maps->mapsize)
- start_bss_libsimgrid = reg.start_addr;
- }else if (!memcmp(basename(maps->regions[i].pathname), basename(xbt_binary_name), strlen(basename(xbt_binary_name)))){
- start_data_binary = reg.start_addr;
- i++;
- reg = maps->regions[i];
- if(reg.pathname == NULL && (reg.prot & PROT_WRITE) && reg.start_addr != std_heap && reg.start_addr != raw_heap && i < maps->mapsize){
- start_bss_binary = reg.start_addr;
- i++;
- }
- }else if(!memcmp(maps->regions[i].pathname, "[stack]", 7)){
+ if (maps->regions[i].pathname == NULL) {
+ // Nothing to do
+ }
+ else if ((reg.prot & PROT_WRITE) && !memcmp(maps->regions[i].pathname, "[stack]", 7)){
maestro_stack_start = reg.start_addr;
maestro_stack_end = reg.end_addr;
- i++;
- }
- }
- }else if ((reg.prot & PROT_READ) && (reg.prot & PROT_EXEC)){
- if (maps->regions[i].pathname != NULL){
- if (!memcmp(basename(maps->regions[i].pathname), "libsimgrid", 10)){
- start_text_libsimgrid = reg.start_addr;
+ } else if ((reg.prot & PROT_READ) && (reg.prot & PROT_EXEC) && !memcmp(basename(maps->regions[i].pathname), "libsimgrid", 10)){
+ if(libsimgrid_path == NULL)
libsimgrid_path = strdup(maps->regions[i].pathname);
- }else if (!memcmp(basename(maps->regions[i].pathname), basename(xbt_binary_name), strlen(basename(xbt_binary_name)))){
- start_text_binary = reg.start_addr;
- }
- }
}
i++;
}
-
- MC_free_memory_map(maps);
-
-}
-
-void MC_get_libsimgrid_plt_section(){
- FILE *fp;
- char *line = NULL; /* Temporal storage for each line that is readed */
- ssize_t read; /* Number of bytes readed */
- size_t n = 0; /* Amount of bytes to read by xbt_getline */
+ xbt_assert(maestro_stack_start, "maestro_stack_start");
+ xbt_assert(maestro_stack_end, "maestro_stack_end");
+ xbt_assert(libsimgrid_path, "libsimgrid_path&");
- char *lfields[7];
- int i, plt_found = 0;
- unsigned long int size, offset;
-
- char *command = bprintf("objdump --section-headers %s", libsimgrid_path);
+ MC_free_memory_map(maps);
- fp = popen(command, "r");
+}
- if(fp == NULL){
- perror("popen failed");
- xbt_abort();
+/** \brief Fill/llokup the "subtype" field.
+ */
+static void MC_resolve_subtype(mc_object_info_t info, dw_type_t type) {
+
+ if(type->dw_type_id==NULL)
+ return;
+ type->subtype = xbt_dict_get_or_null(info->types, type->dw_type_id);
+ if(type->subtype==NULL)
+ return;
+ if(type->subtype->byte_size != 0)
+ return;
+ if(type->subtype->name==NULL)
+ return;
+ // Try to find a more complete description of the type:
+ // We need to fix in order to support C++.
+
+ dw_type_t subtype = xbt_dict_get_or_null(info->types_by_name, type->subtype->name);
+ if(subtype!=NULL) {
+ type->subtype = subtype;
}
- while ((read = xbt_getline(&line, &n, fp)) != -1 && plt_found != 2) {
-
- if(n == 0)
- continue;
-
- /* Wipeout the new line character */
- line[read - 1] = '\0';
-
- lfields[0] = strtok(line, " ");
-
- if(lfields[0] == NULL)
- continue;
-
- if(strcmp(lfields[0], "Sections:") == 0 || strcmp(lfields[0], "Idx") == 0 || strncmp(lfields[0], libsimgrid_path, strlen(libsimgrid_path)) == 0)
- continue;
+ // TODO, support "switch type" (looking up the type in another lib) when possible
+}
- for (i = 1; i < 7 && lfields[i - 1] != NULL; i++) {
- lfields[i] = strtok(NULL, " ");
- }
+void MC_post_process_types(mc_object_info_t info) {
+ xbt_dict_cursor_t cursor = NULL;
+ char *origin;
+ dw_type_t type;
- if(i>=6){
- if(strcmp(lfields[1], ".plt") == 0){
- size = strtoul(lfields[2], NULL, 16);
- offset = strtoul(lfields[5], NULL, 16);
- start_plt_libsimgrid = (char *)start_text_libsimgrid + offset;
- end_plt_libsimgrid = (char *)start_plt_libsimgrid + size;
- plt_found++;
- }else if(strcmp(lfields[1], ".got.plt") == 0){
- size = strtoul(lfields[2], NULL, 16);
- offset = strtoul(lfields[5], NULL, 16);
- start_got_plt_libsimgrid = (char *)start_text_libsimgrid + offset;
- end_got_plt_libsimgrid = (char *)start_got_plt_libsimgrid + size;
- plt_found++;
- }
+ // Lookup "subtype" field:
+ xbt_dict_foreach(info->types, cursor, origin, type){
+ MC_resolve_subtype(info, type);
+ dw_type_t member;
+ unsigned int i = 0;
+ if(type->members!=NULL) xbt_dynar_foreach(type->members, i, member) {
+ MC_resolve_subtype(info, member);
}
-
}
-
- xbt_free(command);
- xbt_free(line);
- pclose(fp);
-
}
-void MC_get_binary_plt_section(){
-
- FILE *fp;
- char *line = NULL; /* Temporal storage for each line that is readed */
- ssize_t read; /* Number of bytes readed */
- size_t n = 0; /* Amount of bytes to read by xbt_getline */
-
- char *lfields[7];
- int i, plt_found = 0;
- unsigned long int size;
+/** \brief Fills the position of the .bss and .data sections. */
+void MC_find_object_address(memory_map_t maps, mc_object_info_t result) {
- char *command = bprintf( "objdump --section-headers %s", xbt_binary_name);
-
- fp = popen(command, "r");
-
- if(fp == NULL){
- perror("popen failed");
- xbt_abort();
- }
-
- while ((read = xbt_getline(&line, &n, fp)) != -1 && plt_found != 2) {
-
- if(n == 0)
- continue;
-
- /* Wipeout the new line character */
- line[read - 1] = '\0';
-
- lfields[0] = strtok(line, " ");
-
- if(lfields[0] == NULL)
- continue;
-
- if(strcmp(lfields[0], "Sections:") == 0 || strcmp(lfields[0], "Idx") == 0 || strncmp(lfields[0], basename(xbt_binary_name), strlen(xbt_binary_name)) == 0)
- continue;
-
- for (i = 1; i < 7 && lfields[i - 1] != NULL; i++) {
- lfields[i] = strtok(NULL, " ");
+ unsigned int i = 0;
+ s_map_region_t reg;
+ const char* name = basename(result->file_name);
+ while (i < maps->mapsize) {
+ reg = maps->regions[i];
+ if (maps->regions[i].pathname == NULL || strcmp(basename(maps->regions[i].pathname), name)) {
+ // Nothing to do
}
-
- if(i>=6){
- if(strcmp(lfields[1], ".plt") == 0){
- size = strtoul(lfields[2], NULL, 16);
- start_plt_binary = (void *)strtoul(lfields[3], NULL, 16);
- end_plt_binary = (char *)start_plt_binary + size;
- plt_found++;
- }else if(strcmp(lfields[1], ".got.plt") == 0){
- size = strtoul(lfields[2], NULL, 16);
- start_got_plt_binary = (char *)strtoul(lfields[3], NULL, 16);
- end_got_plt_binary = (char *)start_got_plt_binary + size;
- plt_found++;
- }
+ else if ((reg.prot & PROT_WRITE)){
+ xbt_assert(!result->start_rw,
+ "Multiple read-write segments for %s, not supported",
+ maps->regions[i].pathname);
+ result->start_rw = reg.start_addr;
+ result->end_rw = reg.end_addr;
+ // .bss is usually after the .data:
+ // TODO, use dl_iterate_phdr to be more robust
+ s_map_region_t* next = &(maps->regions[i+1]);
+ if(next->pathname == NULL && (next->prot & PROT_WRITE) && next->start_addr == reg.end_addr) {
+ result->end_rw = maps->regions[i+1].end_addr;
+ }
+ } else if ((reg.prot & PROT_READ) && (reg.prot & PROT_EXEC)){
+ xbt_assert(!result->start_exec,
+ "Multiple executable segments for %s, not supported",
+ maps->regions[i].pathname);
+ result->start_exec = reg.start_addr;
+ result->end_exec = reg.end_addr;
+ }
+ else if((reg.prot & PROT_READ) && !(reg.prot & PROT_EXEC)) {
+ xbt_assert(!result->start_ro,
+ "Multiple read only segments for %s, not supported",
+ maps->regions[i].pathname);
+ result->start_ro = reg.start_addr;
+ result->end_ro = reg.end_addr;
}
-
-
+ i++;
}
- xbt_free(command);
- xbt_free(line);
- pclose(fp);
-
+ xbt_assert(result->file_name);
+ xbt_assert(result->start_rw);
+ xbt_assert(result->start_exec);
}
/************************************* Take Snapshot ************************************/
/****************************************************************************************/
-static void MC_get_hash_global(char *snapshot_hash, void *data1, void *data2){
-
- /* unsigned int cursor = 0; */
- /* size_t offset; */
- /* global_variable_t current_var; */
- /* void *addr_pointed = NULL; */
- /* void *res = NULL; */
-
- /* xbt_strbuff_t clear = xbt_strbuff_new(); */
-
- /* xbt_dynar_foreach(mc_global_variables, cursor, current_var){ */
- /* if(current_var->address < start_data_libsimgrid){ /\* binary *\/ */
- /* offset = (char *)current_var->address - (char *)start_data_binary; */
- /* addr_pointed = *((void **)((char *)data2 + offset)); */
- /* if(((addr_pointed >= start_plt_binary && addr_pointed <= end_plt_binary)) || ((addr_pointed >= std_heap && (char *)addr_pointed <= (char *)std_heap + STD_HEAP_SIZE ))) */
- /* continue; */
- /* res = xbt_malloc0(current_var->size + 1); */
- /* memset(res, 0, current_var->size + 1); */
- /* memcpy(res, (char*)data2 + offset, current_var->size); */
- /* }else{ /\* libsimgrid *\/ */
- /* offset = (char *)current_var->address - (char *)start_data_libsimgrid; */
- /* addr_pointed = *((void **)((char *)data1 + offset)); */
- /* if((addr_pointed >= start_plt_libsimgrid && addr_pointed <= end_plt_libsimgrid) || (addr_pointed >= std_heap && (char *)addr_pointed <= (char *)std_heap + STD_HEAP_SIZE )) */
- /* continue; */
- /* res = xbt_malloc0(current_var->size + 1); */
- /* memset(res, 0, current_var->size + 1); */
- /* memcpy(res, (char*)data1 + offset, current_var->size); */
- /* } */
- /* if(res != NULL){ */
- /* xbt_strbuff_append(clear, (const char*)res); */
- /* xbt_free(res); */
- /* res = NULL; */
- /* } */
- /* } */
-
- /* xbt_sha(clear->data, snapshot_hash); */
-
- /* xbt_strbuff_free(clear); */
-
-}
-
-static void MC_get_hash_local(char *snapshot_hash, xbt_dynar_t stacks){
-
- /* xbt_dynar_t tokens = NULL, s_tokens = NULL; */
- /* unsigned int cursor1 = 0, cursor2 = 0; */
- /* mc_snapshot_stack_t current_stack; */
- /* char *frame_name = NULL; */
- /* void *addr; */
-
- /* xbt_strbuff_t clear = xbt_strbuff_new(); */
-
- /* while(cursor1 < xbt_dynar_length(stacks)){ */
- /* current_stack = xbt_dynar_get_as(stacks, cursor1, mc_snapshot_stack_t); */
- /* tokens = xbt_str_split(current_stack->local_variables->data, NULL); */
- /* cursor2 = 0; */
- /* while(cursor2 < xbt_dynar_length(tokens)){ */
- /* s_tokens = xbt_str_split(xbt_dynar_get_as(tokens, cursor2, char *), "="); */
- /* if(xbt_dynar_length(s_tokens) > 1){ */
- /* if(strcmp(xbt_dynar_get_as(s_tokens, 0, char *), "frame_name") == 0){ */
- /* xbt_free(frame_name); */
- /* frame_name = xbt_strdup(xbt_dynar_get_as(s_tokens, 1, char *)); */
- /* xbt_strbuff_append(clear, (const char*)xbt_dynar_get_as(tokens, cursor2, char *)); */
- /* cursor2++; */
- /* xbt_dynar_free(&s_tokens); */
- /* continue; */
- /* } */
- /* addr = (void *) strtoul(xbt_dynar_get_as(s_tokens, 1, char *), NULL, 16); */
- /* if(addr > std_heap && (char *)addr <= (char *)std_heap + STD_HEAP_SIZE){ */
- /* cursor2++; */
- /* xbt_dynar_free(&s_tokens); */
- /* continue; */
- /* } */
- /* if(is_stack_ignore_variable(frame_name, xbt_dynar_get_as(s_tokens, 0, char *))){ */
- /* cursor2++; */
- /* xbt_dynar_free(&s_tokens); */
- /* continue; */
- /* } */
- /* xbt_strbuff_append(clear, (const char *)xbt_dynar_get_as(tokens, cursor2, char *)); */
- /* } */
- /* xbt_dynar_free(&s_tokens); */
- /* cursor2++; */
- /* } */
- /* xbt_dynar_free(&tokens); */
- /* cursor1++; */
- /* } */
-
- /* xbt_free(frame_name); */
-
- /* xbt_sha(clear->data, snapshot_hash); */
-
- /* xbt_strbuff_free(clear); */
-
-}
-
-static xbt_dynar_t MC_get_local_variables_values(void *stack_context){
-
- unw_cursor_t c;
- int ret;
-
- char frame_name[256];
-
- ret = unw_init_local(&c, (unw_context_t *)stack_context);
- if(ret < 0){
- XBT_INFO("unw_init_local failed");
- xbt_abort();
- }
-
- unw_word_t ip, sp, off;
- dw_frame_t frame;
-
- unsigned int cursor = 0;
- dw_variable_t current_variable;
- dw_location_entry_t entry = NULL;
- dw_location_t location_entry = NULL;
- unw_word_t res;
- int frame_found = 0, region_type;
- void *frame_pointer_address = NULL;
- unsigned long true_ip, value;
- int stop = 0;
+static xbt_dynar_t MC_get_local_variables_values(xbt_dynar_t stack_frames){
+ unsigned cursor1 = 0;
+ mc_stack_frame_t stack_frame;
xbt_dynar_t variables = xbt_dynar_new(sizeof(local_variable_t), local_variable_free_voidp);
- while(ret >= 0 && !stop){
-
- unw_get_reg(&c, UNW_REG_IP, &ip);
- unw_get_reg(&c, UNW_REG_SP, &sp);
+ xbt_dynar_foreach(stack_frames,cursor1,stack_frame) {
- unw_get_proc_name(&c, frame_name, sizeof (frame_name), &off);
-
- if(!strcmp(frame_name, "smx_ctx_sysv_wrapper")) /* Stop before context switch with maestro */
- stop = 1;
-
- if((uintptr_t)ip > (uintptr_t)start_text_libsimgrid)
- frame = xbt_dict_get_or_null(mc_local_variables_libsimgrid, frame_name);
- else
- frame = xbt_dict_get_or_null(mc_local_variables_binary, frame_name);
-
- if(frame == NULL){
- ret = unw_step(&c);
- continue;
- }
-
- true_ip = (unsigned long)frame->low_pc + (unsigned long)off;
- frame_pointer_address = NULL;
-
- /* Get frame pointer */
- switch(frame->frame_base->type){
- case e_dw_loclist:
- cursor = 0;
- while(cursor < xbt_dynar_length(frame->frame_base->location.loclist) && !frame_found){
- entry = xbt_dynar_get_as(frame->frame_base->location.loclist, cursor, dw_location_entry_t);
- if((true_ip >= entry->lowpc) && (true_ip < entry->highpc)){
- frame_found = 1;
- switch(entry->location->type){
- case e_dw_compose:
- if(xbt_dynar_length(entry->location->location.compose) > 1){
- frame_pointer_address = NULL; /* TODO : location list with optimizations enabled */
- }else{
- location_entry = xbt_dynar_get_as(entry->location->location.compose, 0, dw_location_t);
- switch(location_entry->type){
- case e_dw_register:
- unw_get_reg(&c, location_entry->location.reg, &res);
- frame_pointer_address = (void*)(uintptr_t)res;
- break;
- case e_dw_bregister_op:
- unw_get_reg(&c, location_entry->location.breg_op.reg, &res);
- frame_pointer_address = (void*)((uintptr_t)res + location_entry->location.breg_op.offset);
- break;
- default:
- frame_pointer_address = NULL; /* FIXME : implement other cases (with optimizations enabled) */
- break;
- }
- }
- break;
- default:
- frame_pointer_address = NULL; /* FIXME : implement other cases (with optimizations enabled) */
- break;
- }
- }
- cursor++;
- }
- break;
- default :
- frame_pointer_address = NULL; /* FIXME : implement other cases (with optimizations enabled)*/
- break;
- }
-
- frame_found = 0;
- cursor = 0;
-
- xbt_dynar_foreach(frame->variables, cursor, current_variable){
+ unsigned cursor2 = 0;
+ dw_variable_t current_variable;
+ xbt_dynar_foreach(stack_frame->frame->variables, cursor2, current_variable){
- if((uintptr_t)ip > (uintptr_t)start_text_libsimgrid)
+ int region_type;
+ if((long)stack_frame->ip > (long)mc_libsimgrid_info->start_exec)
region_type = 1;
else
region_type = 2;
local_variable_t new_var = xbt_new0(s_local_variable_t, 1);
- new_var->frame = xbt_strdup(frame_name);
- new_var->ip = (unsigned long)ip;
+ new_var->frame = xbt_strdup(stack_frame->frame_name);
+ new_var->ip = stack_frame->ip;
new_var->name = xbt_strdup(current_variable->name);
- new_var->type = strdup(current_variable->type_origin);
+ new_var->type = current_variable->type;
new_var->region= region_type;
- if(current_variable->address.location != NULL){
- switch(current_variable->address.location->type){
- case e_dw_compose:
- if(xbt_dynar_length(current_variable->address.location->location.compose) > 1){
- /* TODO : location list with optimizations enabled */
- }else{
- location_entry = xbt_dynar_get_as(current_variable->address.location->location.compose, 0, dw_location_t);
-
- switch(location_entry->type){
- case e_dw_register:
- unw_get_reg(&c, location_entry->location.reg, &res);
- value = (unsigned long)res;
- break;
- case e_dw_bregister_op:
- unw_get_reg(&c, location_entry->location.breg_op.reg, &res);
- value = (unsigned long)res + location_entry->location.breg_op.offset;
- break;
- case e_dw_fbregister_op:
- if(frame_pointer_address != NULL)
- value = (unsigned long)((char *)frame_pointer_address + location_entry->location.fbreg_op);
- else
- value = 0;
- break;
- default:
- value = 0; /* FIXME : implement other cases (with optimizations enabled)*/
- break;
- }
-
- if(value)
- new_var->address = (void *)value;
- else
- new_var->address = NULL;
- }
- break;
- default :
- break;
- }
+ /* if(current_variable->address!=NULL) {
+ new_var->address = current_variable->address;
+ } else */
+ if(current_variable->location != NULL){
+ new_var->address = (void*) MC_dwarf_resolve_location(
+ &(stack_frame->unw_cursor), current_variable->location, (void*)stack_frame->frame_base);
}
xbt_dynar_push(variables, &new_var);
}
-
- ret = unw_step(&c);
-
}
return variables;
}
+static void MC_stack_frame_free_voipd(void *s){
+ mc_stack_frame_t stack_frame = *(mc_stack_frame_t*)s;
+ if(stack_frame) {
+ xbt_free(stack_frame->frame_name);
+ xbt_free(stack_frame);
+ }
+}
-static void *MC_get_stack_pointer(void *stack_context, void *heap){
+static xbt_dynar_t MC_unwind_stack_frames(void *stack_context) {
+ xbt_dynar_t result = xbt_dynar_new(sizeof(mc_stack_frame_t), MC_stack_frame_free_voipd);
unw_cursor_t c;
+
+ dw_frame_t test = MC_find_function_by_ip(&MC_unwind_stack_frames);
+ xbt_assert(test);
+
int ret;
- unw_word_t sp;
+ for(ret = unw_init_local(&c, (unw_context_t *)stack_context); ret >= 0; ret = unw_step(&c)){
+ mc_stack_frame_t stack_frame = xbt_new(s_mc_stack_frame_t, 1);
+ xbt_dynar_push(result, &stack_frame);
+
+ stack_frame->unw_cursor = c;
+
+ unw_word_t ip, sp;
+
+ unw_get_reg(&c, UNW_REG_IP, &ip);
+ unw_get_reg(&c, UNW_REG_SP, &sp);
- ret = unw_init_local(&c, (unw_context_t *)stack_context);
- if(ret < 0){
+ stack_frame->ip = ip;
+ stack_frame->sp = sp;
+
+ // TODO, use real addresses in frame_t instead of fixing it here
+
+ dw_frame_t frame = MC_find_function_by_ip((void*) ip);
+ stack_frame->frame = frame;
+
+ if(frame) {
+ stack_frame->frame_name = xbt_strdup(frame->name);
+ stack_frame->frame_base = (unw_word_t)mc_find_frame_base((void*)ip, frame, &c);
+ } else {
+ stack_frame->frame_base = 0;
+ }
+
+ /* Stop before context switch with maestro */
+ if(frame!=NULL && frame->name!=NULL && !strcmp(frame->name, "smx_ctx_sysv_wrapper"))
+ break;
+ }
+
+ if(xbt_dynar_length(result) == 0){
XBT_INFO("unw_init_local failed");
xbt_abort();
}
- unw_get_reg(&c, UNW_REG_SP, &sp);
-
- return (char *)heap + ((char *)sp - (char*)std_heap);
-
-}
+ return result;
+};
static xbt_dynar_t MC_take_snapshot_stacks(mc_snapshot_t *snapshot, void *heap){
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));
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)
/* 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"
/************************** 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;
if(xbt_dynar_is_empty(compared_pointers)){
xbt_dynar_push(compared_pointers, &new_pair);
- return;
+ return 1;
}
unsigned int cursor = 0;
int end = xbt_dynar_length(compared_pointers) - 1;
pointers_pair_t pair = NULL;
+ pointers_pair_t* p = (pointers_pair_t*) xbt_dynar_get_ptr(compared_pointers, 0);
+
while(start <= end){
cursor = (start + end) / 2;
- pair = (pointers_pair_t)xbt_dynar_get_as(compared_pointers, cursor, pointers_pair_t);
- if(pair->p1 == p1){
- if(pair->p2 == p2){
- pointers_pair_free(new_pair);
- return;
- }else if(pair->p2 < p2)
- start = cursor + 1;
- else
- end = cursor - 1;
- }else if(pair->p1 < p1){
+ pair = p[cursor];
+ if(pair->p1 < p1){
start = cursor + 1;
- }else{
+ } else if(pair->p1 > p1) {
+ end = cursor - 1 ;
+ } else if(pair->p2 < p2){
+ start = cursor + 1;
+ } else if(pair->p2 > p2) {
end = cursor - 1 ;
+ } else {
+ pointers_pair_free(new_pair);
+ return 0;
}
}
- if(pair->p1 == p1){
- if(pair->p2 < p2)
- xbt_dynar_insert_at(compared_pointers, cursor + 1, &new_pair);
- else
- xbt_dynar_insert_at(compared_pointers, cursor, &new_pair);
- }else{
- if(pair->p1 < p1)
- xbt_dynar_insert_at(compared_pointers, cursor + 1, &new_pair);
- else
- xbt_dynar_insert_at(compared_pointers, cursor, &new_pair);
- }
-
+ if(pair->p1 < p1)
+ xbt_dynar_insert_at(compared_pointers, cursor + 1, &new_pair);
+ else if(pair->p1 > p1)
+ xbt_dynar_insert_at(compared_pointers, cursor, &new_pair);
+ else if(pair->p2 < p2)
+ xbt_dynar_insert_at(compared_pointers, cursor + 1, &new_pair);
+ else if(pair->p2 > p2)
+ xbt_dynar_insert_at(compared_pointers, cursor, &new_pair);
+ else
+ xbt_die("Unrecheable");
+
+ return 1;
}
-static int compare_areas_with_type(void *area1, void *area2, xbt_dict_t types, xbt_dict_t other_types, char *type_id, int region_size, int region_type, void *start_data, int pointer_level){
+static int compare_areas_with_type(void *area1, void *area2, mc_object_info_t info, mc_object_info_t other_info, dw_type_t type, int region_size, int region_type, void *start_data, int pointer_level){
- dw_type_t type = xbt_dict_get_or_null(types, type_id);;
unsigned int cursor = 0;
dw_type_t member, subtype, subsubtype;
int elm_size, i, res, switch_types = 0;
void *addr_pointed1, *addr_pointed2;
switch(type->type){
- case e_dw_base_type:
- case e_dw_enumeration_type:
- case e_dw_union_type:
- return (memcmp(area1, area2, type->size) != 0);
+ case DW_TAG_base_type:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_union_type:
+ return (memcmp(area1, area2, type->byte_size) != 0);
break;
- case e_dw_typedef:
- case e_dw_volatile_type:
- return compare_areas_with_type(area1, area2, types, other_types, type->dw_type_id, region_size, region_type, start_data, pointer_level);
+ case DW_TAG_typedef:
+ case DW_TAG_volatile_type:
+ case DW_TAG_const_type:
+ return compare_areas_with_type(area1, area2, info, other_info, type->subtype, region_size, region_type, start_data, pointer_level);
break;
- case e_dw_const_type: /* Const variable cannot be modified */
- return -1;
- break;
- case e_dw_array_type:
- subtype = xbt_dict_get_or_null(types, type->dw_type_id);
+ case DW_TAG_array_type:
+ subtype = type->subtype;
switch(subtype->type){
- case e_dw_base_type:
- case e_dw_enumeration_type:
- case e_dw_pointer_type:
- case e_dw_structure_type:
- case e_dw_union_type:
- if(subtype->size == 0){ /*declaration of the type, need the complete description */
- subtype = xbt_dict_get_or_null(types, get_type_description(types, subtype->name));
- if(subtype == NULL){
- subtype = xbt_dict_get_or_null(other_types, get_type_description(other_types, subtype->name));
+ case DW_TAG_base_type:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_pointer_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ if(subtype->byte_size == 0){ /*declaration of the type, need the complete description */
+ subtype = subtype->other_object_same_type;
switch_types = 1;
- }
}
- elm_size = subtype->size;
+ elm_size = subtype->byte_size;
break;
- case e_dw_typedef:
- case e_dw_volatile_type:
- subsubtype = xbt_dict_get_or_null(types, subtype->dw_type_id);
- if(subsubtype->size == 0){ /*declaration of the type, need the complete description */
- subsubtype = xbt_dict_get_or_null(types, get_type_description(types, subsubtype->name));
- if(subsubtype == NULL){
- subsubtype = xbt_dict_get_or_null(other_types, get_type_description(other_types, subsubtype->name));
+ case DW_TAG_const_type:
+ case DW_TAG_typedef:
+ case DW_TAG_volatile_type:
+ subsubtype = subtype->subtype;
+ if(subsubtype->byte_size == 0){ /*declaration of the type, need the complete description */
+ subsubtype = subsubtype->other_object_same_type;
switch_types = 1;
- }
}
- elm_size = subsubtype->size;
+ elm_size = subsubtype->byte_size;
break;
default :
return 0;
break;
}
- for(i=0; i<type->size; i++){
+ for(i=0; i<type->element_count; i++){
if(switch_types)
- res = compare_areas_with_type((char *)area1 + (i*elm_size), (char *)area2 + (i*elm_size), other_types, types, type->dw_type_id, region_size, region_type, start_data, pointer_level);
+ res = compare_areas_with_type((char *)area1 + (i*elm_size), (char *)area2 + (i*elm_size), other_info, info, type->subtype, region_size, region_type, start_data, pointer_level);
else
- res = compare_areas_with_type((char *)area1 + (i*elm_size), (char *)area2 + (i*elm_size), types, other_types, type->dw_type_id, region_size, region_type, start_data, pointer_level);
+ res = compare_areas_with_type((char *)area1 + (i*elm_size), (char *)area2 + (i*elm_size), info, other_info, type->subtype, region_size, region_type, start_data, pointer_level);
if(res == 1)
return res;
}
break;
- case e_dw_pointer_type:
- if(type->dw_type_id && ((dw_type_t)xbt_dict_get_or_null(types, type->dw_type_id))->type == e_dw_subroutine_type){
+ case DW_TAG_pointer_type:
+ if(type->subtype && type->subtype->type == DW_TAG_subroutine_type){
addr_pointed1 = *((void **)(area1));
addr_pointed2 = *((void **)(area2));
return (addr_pointed1 != addr_pointed2);
if(addr_pointed1 == NULL && addr_pointed2 == NULL)
return 0;
- if(already_compared_pointers(addr_pointed1, addr_pointed2) != -1)
+ if(!add_compared_pointers(addr_pointed1, addr_pointed2))
return 0;
- add_compared_pointers(addr_pointed1, addr_pointed2);
pointer_level++;
- if(addr_pointed1 > std_heap && (char *)addr_pointed1 < (char*) std_heap + STD_HEAP_SIZE && addr_pointed2 > std_heap && (char *)addr_pointed2 < (char*) std_heap + STD_HEAP_SIZE){
- return compare_heap_area(addr_pointed1, addr_pointed2, NULL, types, other_types, type->dw_type_id, pointer_level);
- }else if(addr_pointed1 > start_data && (char*)addr_pointed1 <= (char *)start_data + region_size && addr_pointed2 > start_data && (char*)addr_pointed2 <= (char *)start_data + region_size){
+ // Some cases are not handled here:
+ // * the pointers lead to different areas (one to the heap, the other to the RW segment ...);
+ // * a pointer leads to the read-only segment of the current object;
+ // * a pointer lead to a different ELF object.
+
+ // The pointers are both in the heap:
+ if(addr_pointed1 > std_heap && (char *)addr_pointed1 < (char*) std_heap + STD_HEAP_SIZE){
+ if(!(addr_pointed2 > std_heap && (char *)addr_pointed2 < (char*) std_heap + STD_HEAP_SIZE))
+ return 1;
+ return compare_heap_area(addr_pointed1, addr_pointed2, NULL, info, other_info, type->dw_type_id, pointer_level);
+ }
+
+ // The pointers are both in the current object R/W segment:
+ else if(addr_pointed1 > start_data && (char*)addr_pointed1 <= (char *)start_data + region_size){
+ if(!(addr_pointed2 > start_data && (char*)addr_pointed2 <= (char *)start_data + region_size))
+ return 1;
if(type->dw_type_id == NULL)
return (addr_pointed1 != addr_pointed2);
else
- return compare_areas_with_type(addr_pointed1, addr_pointed2, types, other_types, type->dw_type_id, region_size, region_type, start_data, pointer_level);
- }else{
+ return compare_areas_with_type(addr_pointed1, addr_pointed2, info, other_info, type->subtype, region_size, region_type, start_data, pointer_level);
+ }
+
+ else{
return (addr_pointed1 != addr_pointed2);
}
}
break;
- case e_dw_structure_type:
+ case DW_TAG_structure_type:
xbt_dynar_foreach(type->members, cursor, member){
- res = compare_areas_with_type((char *)area1 + member->offset, (char *)area2 + member->offset, types, other_types, member->dw_type_id, region_size, region_type, start_data, pointer_level);
+ XBT_DEBUG("Compare member %s", member->name);
+ res = compare_areas_with_type((char *)area1 + member->offset, (char *)area2 + member->offset, info, other_info, member->subtype, region_size, region_type, start_data, pointer_level);
if(res == 1)
return res;
}
break;
- case e_dw_subroutine_type:
+ case DW_TAG_subroutine_type:
return -1;
break;
default:
}
xbt_dynar_t variables;
- xbt_dict_t types, other_types;
int res;
unsigned int cursor = 0;
dw_variable_t current_var;
size_t offset;
void *start_data;
+ void* start_data_binary = mc_binary_info->start_rw;
+ void* start_data_libsimgrid = mc_libsimgrid_info->start_rw;
+ mc_object_info_t object_info = NULL;
+ mc_object_info_t other_object_info = NULL;
if(region_type == 2){
- variables = mc_global_variables_binary;
- types = mc_variables_type_binary;
- other_types = mc_variables_type_libsimgrid;
+ object_info = mc_binary_info;
+ other_object_info = mc_libsimgrid_info;
start_data = start_data_binary;
}else{
- variables = mc_global_variables_libsimgrid;
- types = mc_variables_type_libsimgrid;
- other_types = mc_variables_type_binary;
+ object_info = mc_libsimgrid_info;
+ other_object_info = mc_binary_info;
start_data = start_data_libsimgrid;
}
+ variables = object_info->global_variables;
xbt_dynar_foreach(variables, cursor, current_var){
- if(region_type == 2)
- offset = (char *)current_var->address.address - (char *)start_data_binary;
- else
- offset = (char *)current_var->address.address - (char *)start_data_libsimgrid;
+ // If the variable is not in this object, skip it:
+ // We do not expect to find a pointer to something which is not reachable
+ // by the global variables.
+ if((char*) current_var->address < (char*) object_info->start_rw
+ || (char*) current_var->address > (char*) object_info->end_rw)
+ continue;
+
+ offset = (char *)current_var->address - (char *)object_info->start_rw;
- res = compare_areas_with_type((char *)r1->data + offset, (char *)r2->data + offset, types, other_types, current_var->type_origin, r1->size, region_type, start_data, 0);
+ dw_type_t bvariable_type = current_var->type;
+ res = compare_areas_with_type((char *)r1->data + offset, (char *)r2->data + offset, object_info, other_object_info, bvariable_type, r1->size, region_type, start_data, 0);
if(res == 1){
XBT_VERB("Global variable %s (%p - %p) is different between snapshots", current_var->name, (char *)r1->data + offset, (char *)r2->data + offset);
xbt_dynar_free(&compared_pointers);
}
static int compare_local_variables(mc_snapshot_stack_t stack1, mc_snapshot_stack_t stack2, void *heap1, void *heap2){
+ void* start_data_binary = mc_binary_info->start_rw;
+ void* start_data_libsimgrid = mc_libsimgrid_info->start_rw;
if(!compared_pointers){
compared_pointers = xbt_dynar_new(sizeof(pointers_pair_t), pointers_pair_free_voidp);
}
offset1 = (char *)current_var1->address - (char *)std_heap;
offset2 = (char *)current_var2->address - (char *)std_heap;
- if(current_var1->region == 1)
- res = compare_areas_with_type( (char *)heap1 + offset1, (char *)heap2 + offset2, mc_variables_type_libsimgrid, mc_variables_type_binary, current_var1->type, 0, 1, start_data_libsimgrid, 0);
- else
- res = compare_areas_with_type( (char *)heap1 + offset1, (char *)heap2 + offset2, mc_variables_type_binary, mc_variables_type_libsimgrid, current_var1->type, 0, 2, start_data_binary, 0);
+ XBT_DEBUG("Compare local variable %s of frame %s", current_var1->name, current_var1->frame);
+
+
+ if(current_var1->region == 1) {
+ dw_type_t subtype = current_var1->type;
+ res = compare_areas_with_type( (char *)heap1 + offset1, (char *)heap2 + offset2, mc_libsimgrid_info, mc_binary_info, subtype, 0, 1, start_data_libsimgrid, 0);
+ } else {
+ dw_type_t subtype = current_var2->type;
+ res = compare_areas_with_type( (char *)heap1 + offset1, (char *)heap2 + offset2, mc_binary_info, mc_libsimgrid_info, subtype, 0, 2, start_data_binary, 0);
+ }
if(res == 1){
XBT_VERB("Local variable %s (%p - %p) in frame %s is different between snapshots", current_var1->name,(char *)heap1 + offset1, (char *)heap2 + offset2, current_var1->frame);
xbt_dynar_free(&compared_pointers);
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];
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){
cursor++;
}
- #ifdef MC_DEBUG
- if(is_diff == 0)
- xbt_os_walltimer_stop(timer);
- xbt_os_walltimer_start(timer);
- #endif
- /* Compare binary global variables */
- is_diff = compare_global_variables(2, s1->regions[2], s2->regions[2]);
- if(is_diff != 0){
- #ifdef MC_DEBUG
- xbt_os_walltimer_stop(timer);
- mc_comp_times->binary_global_variables_comparison_time = xbt_os_timer_elapsed(timer);
- XBT_DEBUG("(%d - %d) Different global variables in binary", num1, num2);
- errors++;
- #else
- #ifdef MC_VERBOSE
- XBT_VERB("(%d - %d) Different global variables in binary", num1, num2);
- #endif
- reset_heap_information();
- xbt_os_walltimer_stop(timer);
- xbt_os_timer_free(timer);
- xbt_os_walltimer_stop(global_timer);
- mc_snapshot_comparison_time = xbt_os_timer_elapsed(global_timer);
- xbt_os_timer_free(global_timer);
+ const char* names[3] = { "?", "libsimgrid", "binary" };
+#ifdef MC_DEBUG
+ double *times[3] = {
+ NULL,
+ &mc_comp_times->libsimgrid_global_variables_comparison_time,
+ &mc_comp_times->binary_global_variables_comparison_time
+ };
+#endif
- return 1;
+ int k=0;
+ for(k=2; k!=0; --k) {
+ #ifdef MC_DEBUG
+ if(is_diff == 0)
+ xbt_os_walltimer_stop(timer);
+ xbt_os_walltimer_start(timer);
#endif
- }
- #ifdef MC_DEBUG
- if(is_diff == 0)
- xbt_os_walltimer_stop(timer);
- xbt_os_walltimer_start(timer);
- #endif
-
- /* Compare libsimgrid global variables */
- is_diff = compare_global_variables(1, s1->regions[1], s2->regions[1]);
+ /* Compare global variables */
+ is_diff = compare_global_variables(k, s1->regions[k], s2->regions[k]);
if(is_diff != 0){
#ifdef MC_DEBUG
xbt_os_walltimer_stop(timer);
- mc_comp_times->libsimgrid_global_variables_comparison_time = xbt_os_timer_elapsed(timer);
- XBT_DEBUG("(%d - %d) Different global variables in libsimgrid", num1, num2);
+ *times[k] = xbt_os_timer_elapsed(timer);
+ XBT_DEBUG("(%d - %d) Different global variables in %s", num1, num2, names[k]);
errors++;
#else
#ifdef MC_VERBOSE
- XBT_VERB("(%d - %d) Different global variables in libsimgrid", num1, num2);
+ XBT_VERB("(%d - %d) Different global variables in %s", num1, num2, names[k]);
#endif
-
+
reset_heap_information();
xbt_os_walltimer_stop(timer);
xbt_os_timer_free(timer);
return 1;
#endif
}
+ }
#ifdef MC_DEBUG
xbt_os_walltimer_start(timer);
#endif
/* Compare heap */
- if(mmalloc_compare_heap((xbt_mheap_t)s1->regions[0]->data, (xbt_mheap_t)s2->regions[0]->data, mc_variables_type_libsimgrid, mc_variables_type_binary) > 0){
+ if(mmalloc_compare_heap((xbt_mheap_t)s1->regions[0]->data,
+ (xbt_mheap_t)s2->regions[0]->data,
+ mc_libsimgrid_info,
+ mc_binary_info) > 0){
#ifdef MC_DEBUG
xbt_os_walltimer_stop(timer);
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;
}
xbt_dynar_t visited_states;
xbt_dict_t first_enabled_state;
+xbt_dynar_t initial_communications_pattern;
+xbt_dynar_t communications_pattern;
+int nb_comm_pattern;
/********** Static functions ***********/
+static void comm_pattern_free(mc_comm_pattern_t p){
+ xbt_free(p->rdv);
+ xbt_free(p->data);
+ xbt_free(p);
+ p = NULL;
+}
+
+static void comm_pattern_free_voidp( void *p){
+ comm_pattern_free((mc_comm_pattern_t) * (void **)p);
+}
+
+static mc_comm_pattern_t get_comm_pattern_from_idx(xbt_dynar_t pattern, unsigned int *idx, e_smx_comm_type_t type, unsigned long proc){
+ mc_comm_pattern_t current_comm;
+ while(*idx < xbt_dynar_length(pattern)){
+ current_comm = (mc_comm_pattern_t)xbt_dynar_get_as(pattern, *idx, mc_comm_pattern_t);
+ if(current_comm->type == type && type == SIMIX_COMM_SEND){
+ if(current_comm->src_proc == proc)
+ return current_comm;
+ }else if(current_comm->type == type && type == SIMIX_COMM_RECEIVE){
+ if(current_comm->dst_proc == proc)
+ return current_comm;
+ }
+ (*idx)++;
+ }
+ return NULL;
+}
+
+static int compare_comm_pattern(mc_comm_pattern_t comm1, mc_comm_pattern_t comm2){
+ if(strcmp(comm1->rdv, comm2->rdv) != 0)
+ return 1;
+ if(comm1->src_proc != comm2->src_proc)
+ return 1;
+ if(comm1->dst_proc != comm2->dst_proc)
+ return 1;
+ if(comm1->data_size != comm2->data_size)
+ return 1;
+ if(memcmp(comm1->data, comm2->data, comm1->data_size) != 0)
+ return 1;
+ return 0;
+}
+
+static void deterministic_pattern(xbt_dynar_t initial_pattern, xbt_dynar_t pattern){
+ unsigned int cursor = 0, send_index = 0, recv_index = 0;
+ mc_comm_pattern_t comm1, comm2;
+ int comm_comparison = 0;
+ int current_process = 0;
+ while(current_process < simix_process_maxpid){
+ while(cursor < xbt_dynar_length(initial_pattern)){
+ comm1 = (mc_comm_pattern_t)xbt_dynar_get_as(initial_pattern, cursor, mc_comm_pattern_t);
+ if(comm1->type == SIMIX_COMM_SEND && comm1->src_proc == current_process){
+ comm2 = get_comm_pattern_from_idx(pattern, &send_index, comm1->type, current_process);
+ comm_comparison = compare_comm_pattern(comm1, comm2);
+ if(comm_comparison == 1){
+ initial_state_safety->send_deterministic = 0;
+ initial_state_safety->comm_deterministic = 0;
+ return;
+ }
+ send_index++;
+ }else if(comm1->type == SIMIX_COMM_RECEIVE && comm1->dst_proc == current_process){
+ comm2 = get_comm_pattern_from_idx(pattern, &recv_index, comm1->type, current_process);
+ comm_comparison = compare_comm_pattern(comm1, comm2);
+ if(comm_comparison == 1){
+ initial_state_safety->comm_deterministic = 0;
+ }
+ recv_index++;
+ }
+ cursor++;
+ }
+ cursor = 0;
+ send_index = 0;
+ recv_index = 0;
+ current_process++;
+ }
+ // XBT_DEBUG("Communication-deterministic : %d, Send-deterministic : %d", initial_state_safety->comm_deterministic, initial_state_safety->send_deterministic);
+}
+
+static int complete_comm_pattern(xbt_dynar_t list, mc_comm_pattern_t pattern){
+ mc_comm_pattern_t current_pattern;
+ unsigned int cursor = 0;
+ xbt_dynar_foreach(list, cursor, current_pattern){
+ if(current_pattern->comm == pattern->comm){
+ if(!current_pattern->completed){
+ current_pattern->src_proc = pattern->comm->comm.src_proc->pid;
+ current_pattern->dst_proc = pattern->comm->comm.dst_proc->pid;
+ current_pattern->data_size = pattern->comm->comm.src_buff_size;
+ current_pattern->data = xbt_malloc0(current_pattern->data_size);
+ current_pattern->matched_comm = pattern->num;
+ memcpy(current_pattern->data, current_pattern->comm->comm.src_buff, current_pattern->data_size);
+ current_pattern->completed = 1;
+ return current_pattern->num;
+ }
+ }
+ }
+ return -1;
+}
+
+void get_comm_pattern(xbt_dynar_t list, smx_simcall_t request, int call){
+ mc_comm_pattern_t pattern = NULL;
+ pattern = xbt_new0(s_mc_comm_pattern_t, 1);
+ pattern->num = ++nb_comm_pattern;
+ pattern->completed = 0;
+ if(call == 1){ // ISEND
+ pattern->comm = simcall_comm_isend__get__result(request);
+ pattern->type = SIMIX_COMM_SEND;
+ if(pattern->comm->comm.dst_proc != NULL){
+
+ pattern->matched_comm = complete_comm_pattern(list, pattern);
+ pattern->dst_proc = pattern->comm->comm.dst_proc->pid;
+ pattern->completed = 1;
+ }
+ pattern->src_proc = pattern->comm->comm.src_proc->pid;
+ pattern->data_size = pattern->comm->comm.src_buff_size;
+ pattern->data=xbt_malloc0(pattern->data_size);
+ memcpy(pattern->data, pattern->comm->comm.src_buff, pattern->data_size);
+ }else{ // IRECV
+ pattern->comm = simcall_comm_irecv__get__result(request);
+ pattern->type = SIMIX_COMM_RECEIVE;
+ if(pattern->comm->comm.src_proc != NULL){
+ pattern->matched_comm = complete_comm_pattern(list, pattern);
+ pattern->src_proc = pattern->comm->comm.src_proc->pid;
+ pattern->completed = 1;
+ pattern->data_size = pattern->comm->comm.src_buff_size;
+ pattern->data=xbt_malloc0(pattern->data_size);
+ memcpy(pattern->data, pattern->comm->comm.src_buff, pattern->data_size);
+ }
+ pattern->dst_proc = pattern->comm->comm.dst_proc->pid;
+ }
+ if(pattern->comm->comm.rdv != NULL)
+ pattern->rdv = strdup(pattern->comm->comm.rdv->name);
+ else
+ pattern->rdv = strdup(pattern->comm->comm.rdv_cpy->name);
+ xbt_dynar_push(list, &pattern);
+}
+
+static void print_communications_pattern(xbt_dynar_t comms_pattern){
+ unsigned int cursor = 0;
+ mc_comm_pattern_t current_comm;
+ xbt_dynar_foreach(comms_pattern, cursor, current_comm){
+ // fprintf(stderr, "%s (%d - comm %p, src : %lu, dst %lu, rdv name %s, data %p, matched with %d)\n", current_comm->type == SIMIX_COMM_SEND ? "iSend" : "iRecv", current_comm->num, current_comm->comm, current_comm->src_proc, current_comm->dst_proc, current_comm->rdv, current_comm->data, current_comm->matched_comm);
+ }
+}
+
static void visited_state_free(mc_visited_state_t state){
if(state){
MC_free_snapshot(state->system_state);
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;
}
+/** \brief Find a suitable subrange of candidate duplicates for a given state
+ *
+ * \param all_ pairs dynamic array of states with candidate duplicates of the current state;
+ * \param pair current state;
+ * \param min (output) index of the beginning of the the subrange
+ * \param max (output) index of the enf of the subrange
+ *
+ * Given a suitably ordered array of state, this function extracts a subrange
+ * (with index *min <= i <= *max) with candidate duplicates of the given state.
+ * This function uses only fast discriminating criterions and does not use the
+ * full state comparison algorithms.
+ *
+ * The states in all_pairs MUST be ordered using a (given) weak order
+ * (based on nb_processes and heap_bytes_used).
+ * The subrange is the subrange of "equivalence" of the given state.
+ */
static int get_search_interval(xbt_dynar_t all_states, mc_visited_state_t state, int *min, int *max){
int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
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)
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);
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
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);
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;
min2 = state_test->num;
}
}
+
+ // and drop it:
xbt_dynar_remove_at(visited_states, index2, NULL);
}
/* 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("**************************************************");
}
-/**
- * \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)
{
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) {
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++;
xbt_dict_remove(first_enabled_state, key);
xbt_free(key);
MC_UNSET_RAW_MEM;
+
+ if(_sg_mc_comms_determinism){
+ if(req->call == SIMCALL_COMM_ISEND)
+ comm_pattern = 1;
+ else if(req->call == SIMCALL_COMM_IRECV)
+ comm_pattern = 2;
+ }
/* Answer the request */
SIMIX_simcall_pre(req, value); /* After this call req is no longer usefull */
+ if(_sg_mc_comms_determinism){
+ MC_SET_RAW_MEM;
+ if(comm_pattern != 0){
+ if(!initial_state_safety->initial_communications_pattern_done)
+ get_comm_pattern(initial_communications_pattern, req, comm_pattern);
+ else
+ get_comm_pattern(communications_pattern, req, comm_pattern);
+ }
+ MC_UNSET_RAW_MEM;
+ comm_pattern = 0;
+ }
+
/* Wait for requests (schedules processes) */
MC_wait_for_requests();
}
- /* Trash the current state, no longer needed */
MC_SET_RAW_MEM;
+
+ if(_sg_mc_comms_determinism){
+ if(!initial_state_safety->initial_communications_pattern_done){
+ //print_communications_pattern(initial_communications_pattern);
+ }else{
+ if(interleave_size == 0){ /* if (interleave_size > 0), process interleaved but not enabled => "incorrect" path, determinism not evaluated */
+ //print_communications_pattern(communications_pattern);
+ deterministic_pattern(initial_communications_pattern, communications_pattern);
+ }
+ }
+ initial_state_safety->initial_communications_pattern_done = 1;
+ }
+
+ /* Trash the current state, no longer needed */
xbt_fifo_shift(mc_stack_safety);
MC_state_delete(state);
XBT_DEBUG("Delete state %d at depth %d", state->num, xbt_fifo_size(mc_stack_safety) + 1);
+
MC_UNSET_RAW_MEM;
/* Check for deadlocks */
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);
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);
}
--- /dev/null
+/* 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);
+
+/** \brief Process a type DIE
+ */
+static void MC_dwarf_handle_type_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit);
+
+/** \brief Calls MC_dwarf_handle_die on all childrend of the given die
+ *
+ * \param info the resulting object fot the library/binary file (output)
+ * \param die the current DIE
+ * \param unit the DIE of the compile unit of the current DIE
+ * \param frame containg frame if any
+ */
+static void MC_dwarf_handle_children(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame);
+
+/** \brief Handle a variable (DW_TAG_variable or other)
+ *
+ * \param info the resulting object fot the library/binary file (output)
+ * \param die the current DIE
+ * \param unit the DIE of the compile unit of the current DIE
+ * \param frame containg frame if any
+ */
+static void MC_dwarf_handle_variable_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame);
+
+/** \brief Convert a libdw DWARF expression into a MC representation of the location
+ *
+ * \param expr array of DWARf operations
+ * \param len number of elements
+ * \return a new MC expression
+ */
+static dw_location_t MC_dwarf_get_expression(Dwarf_Op* expr, size_t len);
+
+/** \brief Get the DW_TAG_type of the DIE
+ *
+ * \param die DIE
+ * \return DW_TAG_type attribute as a new string (NULL if none)
+ */
+static char* MC_dwarf_at_type(Dwarf_Die* die);
+
+/** \brief Get the name of an attribute (DW_AT_*) from its code
+ *
+ * \param attr attribute code (see the DWARF specification)
+ * \return name of the attribute
+ */
+const char* MC_dwarf_attrname(int attr) {
+ switch (attr) {
+#include "mc_dwarf_attrnames.h"
+ default:
+ return "DW_AT_unkown";
+ }
+}
+
+/** \brief Get the name of a dwarf tag (DW_TAG_*) from its code
+ *
+ * \param tag tag code (see the DWARF specification)
+ * \return name of the tag
+ */
+const char* MC_dwarf_tagname(int tag) {
+ switch (tag) {
+#include "mc_dwarf_tagnames.h"
+ case DW_TAG_invalid:
+ return "DW_TAG_invalid";
+ default:
+ return "DW_TAG_unkown";
+ }
+}
+
+#define MC_DW_CLASS_UNKNOWN 0
+#define MC_DW_CLASS_ADDRESS 1 // Location in the address space of the program
+#define MC_DW_CLASS_BLOCK 2 // Arbitrary block of bytes
+#define MC_DW_CLASS_CONSTANT 3
+#define MC_DW_CLASS_STRING 3 // String
+#define MC_DW_CLASS_FLAG 4 // Boolean
+#define MC_DW_CLASS_REFERENCE 5 // Reference to another DIE
+#define MC_DW_CLASS_EXPRLOC 6 // DWARF expression/location description
+#define MC_DW_CLASS_LINEPTR 7
+#define MC_DW_CLASS_LOCLISTPTR 8
+#define MC_DW_CLASS_MACPTR 9
+#define MC_DW_CLASS_RANGELISTPTR 10
+
+static int MC_dwarf_form_get_class(int form) {
+ switch(form) {
+ case DW_FORM_addr:
+ return MC_DW_CLASS_ADDRESS;
+ case DW_FORM_block2:
+ case DW_FORM_block4:
+ case DW_FORM_block:
+ case DW_FORM_block1:
+ return MC_DW_CLASS_BLOCK;
+ case DW_FORM_data2:
+ case DW_FORM_data4:
+ case DW_FORM_data8:
+ case DW_FORM_udata:
+ case DW_FORM_sdata:
+ return MC_DW_CLASS_CONSTANT;
+ case DW_FORM_string:
+ case DW_FORM_strp:
+ return MC_DW_CLASS_STRING;
+ case DW_FORM_ref_addr:
+ case DW_FORM_ref1:
+ case DW_FORM_ref2:
+ case DW_FORM_ref4:
+ case DW_FORM_ref8:
+ case DW_FORM_ref_udata:
+ return MC_DW_CLASS_REFERENCE;
+ case DW_FORM_flag:
+ case DW_FORM_flag_present:
+ return MC_DW_CLASS_FLAG;
+ case DW_FORM_exprloc:
+ return MC_DW_CLASS_EXPRLOC;
+ // TODO sec offset
+ // TODO indirect
+ default:
+ return MC_DW_CLASS_UNKNOWN;
+ }
+}
+
+/** \brief Get the name of the tag of a given DIE
+ *
+ * \param die DIE
+ * \return name of the tag of this DIE
+ */
+static inline const char* MC_dwarf_die_tagname(Dwarf_Die* die) {
+ return MC_dwarf_tagname(dwarf_tag(die));
+}
+
+// ***** Attributes
+
+/** \brief Get an attribute of a given DIE as a string
+ *
+ * \param the DIE
+ * \param attribute attribute
+ * \return value of the given attribute of the given DIE
+ */
+static const char* MC_dwarf_attr_string(Dwarf_Die* die, int attribute) {
+ Dwarf_Attribute attr;
+ if (!dwarf_attr_integrate(die, attribute, &attr)) {
+ return NULL;
+ } else {
+ return dwarf_formstring(&attr);
+ }
+}
+
+/** \brief Get the linkage name of a DIE.
+ *
+ * Use either DW_AT_linkage_name or DW_AR_MIPS_linkage_name.
+ *
+ * \param DIE
+ * \return linkage name of the given DIE (or NULL)
+ * */
+static const char* MC_dwarf_at_linkage_name(Dwarf_Die* die) {
+ const char* name = MC_dwarf_attr_string(die, DW_AT_linkage_name);
+ if (!name)
+ name = MC_dwarf_attr_string(die, DW_AT_MIPS_linkage_name);
+ return name;
+}
+
+/** \brief Create a location list from a given attribute
+ *
+ * \param die the DIE
+ * \param attr the attribute
+ * \return MC specific representation of the location list represented by the given attribute
+ * of the given die
+ */
+static dw_location_t MC_dwarf_get_location_list(mc_object_info_t info, Dwarf_Die* die, Dwarf_Attribute* attr) {
+
+ dw_location_t location = xbt_new0(s_dw_location_t, 1);
+ location->type = e_dw_loclist;
+ xbt_dynar_t loclist = xbt_dynar_new(sizeof(dw_location_entry_t), NULL);
+ location->location.loclist = loclist;
+
+ ptrdiff_t offset = 0;
+ Dwarf_Addr base, start, end;
+ Dwarf_Op *expr;
+ size_t len;
+
+ while (1) {
+
+ offset = dwarf_getlocations(attr, offset, &base, &start, &end, &expr, &len);
+ if (offset==0)
+ return location;
+ else if (offset==-1)
+ xbt_die("Error while loading location list");
+
+ dw_location_entry_t new_entry = xbt_new0(s_dw_location_entry_t, 1);
+
+ void* base = info->flags & MC_OBJECT_INFO_EXECUTABLE ? 0 : MC_object_base_address(info);
+
+ new_entry->lowpc = (char*) base + start;
+ new_entry->highpc = (char*) base + end;
+ new_entry->location = MC_dwarf_get_expression(expr, len);
+
+ xbt_dynar_push(loclist, &new_entry);
+
+ }
+}
+
+/** \brief Find the frame base of a given frame
+ *
+ * \param ip Instruction pointer
+ * \param frame
+ * \param unw_cursor
+ */
+void* mc_find_frame_base(void* ip, dw_frame_t frame, unw_cursor_t* unw_cursor) {
+ switch(frame->frame_base->type) {
+ case e_dw_loclist:
+ {
+ int loclist_cursor;
+ for(loclist_cursor=0; loclist_cursor < xbt_dynar_length(frame->frame_base->location.loclist); loclist_cursor++){
+ dw_location_entry_t entry = xbt_dynar_get_as(frame->frame_base->location.loclist, loclist_cursor, dw_location_entry_t);
+ if((ip >= entry->lowpc) && (ip < entry->highpc)){
+ return (void*) MC_dwarf_resolve_location(unw_cursor, entry->location, NULL);
+ }
+ }
+ return NULL;
+ }
+ // Not handled:
+ default:
+ return NULL;
+ }
+}
+
+/** \brief Get the location expression or location list from an attribute
+ *
+ * Processes direct expressions as well as location lists.
+ *
+ * \param die the DIE
+ * \param attr the attribute
+ * \return MC specific representation of the location represented by the given attribute
+ * of the given die
+ */
+static dw_location_t MC_dwarf_get_location(mc_object_info_t info, Dwarf_Die* die, Dwarf_Attribute* attr) {
+ int form = dwarf_whatform(attr);
+ switch (form) {
+
+ // The attribute is an DWARF location expression:
+ case DW_FORM_exprloc:
+ case DW_FORM_block1: // not in the spec
+ case DW_FORM_block2:
+ case DW_FORM_block4:
+ case DW_FORM_block:
+ {
+ Dwarf_Op* expr;
+ size_t len;
+ if (dwarf_getlocation(attr, &expr, &len))
+ xbt_die("Could not read location expression");
+ return MC_dwarf_get_expression(expr, len);
+ }
+
+ // The attribute is a reference to a location list entry:
+ case DW_FORM_sec_offset:
+ case DW_FORM_data2:
+ case DW_FORM_data4:
+ case DW_FORM_data8:
+ {
+ return MC_dwarf_get_location_list(info, die, attr);
+ }
+ break;
+
+ default:
+ xbt_die("Unexpected form %i list for location in attribute %s of <%p>%s",
+ form,
+ MC_dwarf_attrname(attr->code),
+ (void*) dwarf_dieoffset(die),
+ MC_dwarf_attr_string(die, DW_AT_name));
+ return NULL;
+ }
+}
+
+/** \brief Get the location expression or location list from an attribute
+ *
+ * Processes direct expressions as well as location lists.
+ *
+ * \param die the DIE
+ * \param attribute the attribute code
+ * \return MC specific representation of the location represented by the given attribute
+ * of the given die
+ */
+static dw_location_t MC_dwarf_at_location(mc_object_info_t info, Dwarf_Die* die, int attribute) {
+ if(!dwarf_hasattr_integrate(die, attribute))
+ return xbt_new0(s_dw_location_t, 1);
+
+ Dwarf_Attribute attr;
+ dwarf_attr_integrate(die, attribute, &attr);
+ return MC_dwarf_get_location(info, die, &attr);
+}
+
+static char* MC_dwarf_at_type(Dwarf_Die* die) {
+ Dwarf_Attribute attr;
+ if (dwarf_hasattr_integrate(die, DW_AT_type)) {
+ dwarf_attr_integrate(die, DW_AT_type, &attr);
+ Dwarf_Die subtype_die;
+ if (dwarf_formref_die(&attr, &subtype_die)==NULL) {
+ xbt_die("Could not find DIE for type");
+ }
+ Dwarf_Off subtype_global_offset = dwarf_dieoffset(&subtype_die);
+ return bprintf("%" PRIx64 , subtype_global_offset);
+ }
+ else return NULL;
+}
+
+static uint64_t MC_dwarf_attr_addr(Dwarf_Die* die, int attribute) {
+ Dwarf_Attribute attr;
+ if(dwarf_attr_integrate(die, attribute, &attr)==NULL)
+ return 0;
+ Dwarf_Addr value;
+ if (dwarf_formaddr(&attr, &value) == 0)
+ return (uint64_t) value;
+ else
+ return 0;
+}
+
+static uint64_t MC_dwarf_attr_uint(Dwarf_Die* die, int attribute, uint64_t default_value) {
+ Dwarf_Attribute attr;
+ if (dwarf_attr_integrate(die, attribute, &attr)==NULL)
+ return default_value;
+ Dwarf_Word value;
+ return dwarf_formudata(dwarf_attr_integrate(die, attribute, &attr), &value) == 0 ? (uint64_t) value : default_value;
+}
+
+static bool MC_dwarf_attr_flag(Dwarf_Die* die, int attribute, int integrate) {
+ Dwarf_Attribute attr;
+ if ((integrate ? dwarf_attr_integrate(die, attribute, &attr)
+ : dwarf_attr(die, attribute, &attr))==0)
+ return false;
+
+ bool result;
+ if (dwarf_formflag(&attr, &result))
+ xbt_die("Unexpected form for attribute %s",
+ MC_dwarf_attrname(attribute));
+ return result;
+}
+
+static uint64_t MC_dwarf_default_lower_bound(int lang) {
+ switch(lang) {
+ case DW_LANG_C:
+ case DW_LANG_C89:
+ case DW_LANG_C99:
+ case DW_LANG_C_plus_plus:
+ case DW_LANG_D:
+ case DW_LANG_Java:
+ case DW_LANG_ObjC:
+ case DW_LANG_ObjC_plus_plus:
+ case DW_LANG_Python:
+ case DW_LANG_UPC:
+ return 0;
+ case DW_LANG_Ada83:
+ case DW_LANG_Ada95:
+ case DW_LANG_Fortran77:
+ case DW_LANG_Fortran90:
+ case DW_LANG_Fortran95:
+ case DW_LANG_Modula2:
+ case DW_LANG_Pascal83:
+ case DW_LANG_PL1:
+ case DW_LANG_Cobol74:
+ case DW_LANG_Cobol85:
+ return 1;
+ default:
+ xbt_die("No default MT_TAG_lower_bound for language %i and none given", lang);
+ return 0;
+ }
+}
+
+static uint64_t MC_dwarf_subrange_element_count(Dwarf_Die* die, Dwarf_Die* unit) {
+ xbt_assert(dwarf_tag(die)==DW_TAG_enumeration_type ||dwarf_tag(die)==DW_TAG_subrange_type,
+ "MC_dwarf_subrange_element_count called with DIE of type %s", MC_dwarf_die_tagname(die));
+
+ // Use DW_TAG_count if present:
+ if (dwarf_hasattr_integrate(die, DW_AT_count)) {
+ return MC_dwarf_attr_uint(die, DW_AT_count, 0);
+ }
+
+ // Otherwise compute DW_TAG_upper_bound-DW_TAG_lower_bound + 1:
+
+ if (!dwarf_hasattr_integrate(die, DW_AT_upper_bound)) {
+ // This is not really 0, but the code expects this (we do not know):
+ return 0;
+ }
+ uint64_t upper_bound = MC_dwarf_attr_uint(die, DW_AT_upper_bound, -1);
+
+ uint64_t lower_bound = 0;
+ if (dwarf_hasattr_integrate(die, DW_AT_lower_bound)) {
+ lower_bound = MC_dwarf_attr_uint(die, DW_AT_lower_bound, -1);
+ } else {
+ lower_bound = MC_dwarf_default_lower_bound(dwarf_srclang(unit));
+ }
+ return upper_bound - lower_bound + 1;
+}
+
+static uint64_t MC_dwarf_array_element_count(Dwarf_Die* die, Dwarf_Die* unit) {
+ xbt_assert(dwarf_tag(die)==DW_TAG_array_type,
+ "MC_dwarf_array_element_count called with DIE of type %s", MC_dwarf_die_tagname(die));
+
+ int result = 1;
+ Dwarf_Die child;
+ int res;
+ for (res=dwarf_child(die, &child); res==0; res=dwarf_siblingof(&child,&child)) {
+ int child_tag = dwarf_tag(&child);
+ if (child_tag==DW_TAG_subrange_type ||child_tag==DW_TAG_enumeration_type) {
+ result *= MC_dwarf_subrange_element_count(&child, unit);
+ }
+ }
+ return result;
+}
+
+// ***** Location
+
+Dwarf_Off MC_dwarf_resolve_location(unw_cursor_t* c, dw_location_t location, void* frame_pointer_address) {
+ unw_word_t res;
+ switch (location->type){
+ case e_dw_compose:
+ if (xbt_dynar_length(location->location.compose) > 1){
+ return 0; /* TODO : location list with optimizations enabled */
+ }
+ dw_location_t location_entry = xbt_dynar_get_as(location->location.compose, 0, dw_location_t);
+ switch (location_entry->type){
+ case e_dw_register:
+ unw_get_reg(c, location_entry->location.reg, &res);
+ return res;
+ case e_dw_bregister_op:
+ unw_get_reg(c, location_entry->location.breg_op.reg, &res);
+ return (Dwarf_Off) ((long)res + location_entry->location.breg_op.offset);
+ break;
+ case e_dw_fbregister_op:
+ if (frame_pointer_address != NULL)
+ return (Dwarf_Off)((char *)frame_pointer_address + location_entry->location.fbreg_op);
+ else
+ return 0;
+ default:
+ return 0; /* FIXME : implement other cases (with optimizations enabled) */
+ }
+ break;
+ default:
+ return 0;
+ }
+}
+
+// ***** dw_type_t
+
+static void MC_dwarf_fill_member_location(dw_type_t type, dw_type_t member, Dwarf_Die* child) {
+ if (dwarf_hasattr(child, DW_AT_data_bit_offset)) {
+ xbt_die("Can't groke DW_AT_data_bit_offset.");
+ }
+
+ if (!dwarf_hasattr_integrate(child, DW_AT_data_member_location)) {
+ if (type->type != DW_TAG_union_type) {
+ xbt_die(
+ "Missing DW_AT_data_member_location field in DW_TAG_member %s of type <%p>%s",
+ member->name, type->id, type->name);
+ } else {
+ return;
+ }
+ }
+
+ Dwarf_Attribute attr;
+ dwarf_attr_integrate(child, DW_AT_data_member_location, &attr);
+ int klass = MC_dwarf_form_get_class(dwarf_whatform(&attr));
+ switch (klass) {
+ case MC_DW_CLASS_EXPRLOC:
+ case MC_DW_CLASS_BLOCK:
+ // Location expression:
+ {
+ Dwarf_Op* expr;
+ size_t len;
+ if (dwarf_getlocation(&attr, &expr, &len)) {
+ xbt_die(
+ "Could not read location expression DW_AT_data_member_location in DW_TAG_member %s of type <%p>%s",
+ MC_dwarf_attr_string(child, DW_AT_name),
+ type->id, type->name);
+ }
+ if (len==1 && expr[0].atom == DW_OP_plus_uconst) {
+ member->offset = expr[0].number;
+ } else {
+ xbt_die("Can't groke this location expression yet.");
+ }
+ break;
+ }
+ case MC_DW_CLASS_CONSTANT:
+ // Offset from the base address of the object:
+ {
+ Dwarf_Word offset;
+ if (!dwarf_formudata(&attr, &offset))
+ member->offset = offset;
+ else
+ xbt_die("Cannot get %s location <%p>%s",
+ MC_dwarf_attr_string(child, DW_AT_name),
+ type->id, type->name);
+ break;
+ }
+ case MC_DW_CLASS_LOCLISTPTR:
+ // Reference to a location list:
+ // TODO
+ case MC_DW_CLASS_REFERENCE:
+ // It's supposed to be possible in DWARF2 but I couldn't find its semantic
+ // in the spec.
+ default:
+ xbt_die("Can't handle form class 0x%x (%i) as DW_AT_member_location", klass, klass);
+ }
+
+}
+
+static void MC_dwarf_add_members(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_type_t type) {
+ int res;
+ Dwarf_Die child;
+ xbt_assert(!type->members);
+ type->members = xbt_dynar_new(sizeof(dw_type_t), (void(*)(void*))dw_type_free);
+ for (res=dwarf_child(die, &child); res==0; res=dwarf_siblingof(&child,&child)) {
+ if (dwarf_tag(&child)==DW_TAG_member) {
+ // TODO, we should use another type (because is is not a type but a member)
+ dw_type_t member = xbt_new0(s_dw_type_t, 1);
+ member->type = -1;
+ member->id = NULL;
+
+ const char* name = MC_dwarf_attr_string(&child, DW_AT_name);
+ if(name)
+ member->name = xbt_strdup(name);
+ else
+ member->name = NULL;
+
+ member->byte_size = MC_dwarf_attr_uint(&child, DW_AT_byte_size, 0);
+ member->element_count = -1;
+ member->dw_type_id = MC_dwarf_at_type(&child);
+ member->members = NULL;
+ member->is_pointer_type = 0;
+ member->offset = 0;
+
+ if(dwarf_hasattr(&child, DW_AT_data_bit_offset)) {
+ xbt_die("Can't groke DW_AT_data_bit_offset.");
+ }
+
+ MC_dwarf_fill_member_location(type, member, &child);
+
+ if (!member->dw_type_id) {
+ xbt_die("Missing type for member %s of <%p>%s", member->name, type->id, type->name);
+ }
+
+ xbt_dynar_push(type->members, &member);
+ }
+ }
+}
+
+/** \brief Create a MC type object from a DIE
+ *
+ * \param info current object info object
+ * \param DIE (for a given type);
+ * \param unit compilation unit of the current DIE
+ * \return MC representation of the type
+ */
+static dw_type_t MC_dwarf_die_to_type(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit) {
+
+ dw_type_t type = xbt_new0(s_dw_type_t, 1);
+ type->type = -1;
+ type->id = NULL;
+ type->name = NULL;
+ type->byte_size = 0;
+ type->element_count = -1;
+ type->dw_type_id = NULL;
+ type->members = NULL;
+ type->is_pointer_type = 0;
+ type->offset = 0;
+
+ type->type = dwarf_tag(die);
+
+ // Global Offset
+ type->id = (void *) dwarf_dieoffset(die);
+
+ const char* name = MC_dwarf_attr_string(die, DW_AT_name);
+ if (name!=NULL) {
+ type->name = xbt_strdup(name);
+ }
+
+ XBT_DEBUG("Processing type <%p>%s", type->id, type->name);
+
+ type->dw_type_id = MC_dwarf_at_type(die);
+
+ // Computation of the byte_size;
+ if (dwarf_hasattr_integrate(die, DW_AT_byte_size))
+ type->byte_size = MC_dwarf_attr_uint(die, DW_AT_byte_size, 0);
+ else if (type->type == DW_TAG_array_type || type->type==DW_TAG_structure_type || type->type==DW_TAG_class_type) {
+ Dwarf_Word size;
+ if (dwarf_aggregate_size(die, &size)==0) {
+ type->byte_size = size;
+ }
+ }
+
+ switch (type->type) {
+ case DW_TAG_array_type:
+ type->element_count = MC_dwarf_array_element_count(die, unit);
+ // TODO, handle DW_byte_stride and (not) DW_bit_stride
+ break;
+
+ case DW_TAG_pointer_type:
+ case DW_TAG_reference_type:
+ case DW_TAG_rvalue_reference_type:
+ type->is_pointer_type = 1;
+ break;
+
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ case DW_TAG_class_type:
+ MC_dwarf_add_members(info, die, unit, type);
+ }
+
+ return type;
+}
+
+static void MC_dwarf_handle_type_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit) {
+ dw_type_t type = MC_dwarf_die_to_type(info, die, unit);
+
+ char* key = bprintf("%" PRIx64, (uint64_t) type->id);
+ xbt_dict_set(info->types, key, type, NULL);
+
+ if(type->name && type->byte_size!=0) {
+ xbt_dict_set(info->types_by_name, type->name, type, NULL);
+ }
+}
+
+/** \brief Convert libdw location expresion elment into native one (or NULL in some cases) */
+static dw_location_t MC_dwarf_get_expression_element(Dwarf_Op* op) {
+ dw_location_t element = xbt_new0(s_dw_location_t, 1);
+ uint8_t atom = op->atom;
+ if (atom >= DW_OP_reg0 && atom<= DW_OP_reg31) {
+ element->type = e_dw_register;
+ element->location.reg = atom - DW_OP_reg0;
+ }
+ else if (atom >= DW_OP_breg0 && atom<= DW_OP_breg31) {
+ element->type = e_dw_bregister_op;
+ element->location.reg = atom - DW_OP_breg0;
+ element->location.breg_op.offset = op->number;
+ }
+ else if (atom >= DW_OP_lit0 && atom<= DW_OP_lit31) {
+ element->type = e_dw_lit;
+ element->location.reg = atom - DW_OP_lit0;
+ }
+ else switch (atom) {
+ case DW_OP_fbreg:
+ element->type = e_dw_fbregister_op;
+ element->location.fbreg_op = op->number;
+ break;
+ case DW_OP_piece:
+ element->type = e_dw_piece;
+ element->location.piece = op->number;
+ break;
+ case DW_OP_plus_uconst:
+ element->type = e_dw_plus_uconst;
+ element->location.plus_uconst = op->number;
+ break;
+ case DW_OP_abs:
+ element->type = e_dw_arithmetic;
+ element->location.arithmetic = xbt_strdup("abs");
+ break;
+ case DW_OP_and:
+ element->type = e_dw_arithmetic;
+ element->location.arithmetic = xbt_strdup("and");
+ break;
+ case DW_OP_div:
+ element->type = e_dw_arithmetic;
+ element->location.arithmetic = xbt_strdup("div");
+ break;
+ case DW_OP_minus:
+ element->type = e_dw_arithmetic;
+ element->location.arithmetic = xbt_strdup("minus");
+ break;
+ case DW_OP_mod:
+ element->type = e_dw_arithmetic;
+ element->location.arithmetic = xbt_strdup("mod");
+ break;
+ case DW_OP_mul:
+ element->type = e_dw_arithmetic;
+ element->location.arithmetic = xbt_strdup("mul");
+ break;
+ case DW_OP_neg:
+ element->type = e_dw_arithmetic;
+ element->location.arithmetic = xbt_strdup("neg");
+ break;
+ case DW_OP_not:
+ element->type = e_dw_arithmetic;
+ element->location.arithmetic = xbt_strdup("not");
+ break;
+ case DW_OP_or:
+ element->type = e_dw_arithmetic;
+ element->location.arithmetic = xbt_strdup("or");
+ break;
+ case DW_OP_plus:
+ element->type = e_dw_arithmetic;
+ element->location.arithmetic = xbt_strdup("plus");
+ break;
+
+ case DW_OP_stack_value:
+ // Why nothing here?
+ xbt_free(element);
+ return NULL;
+
+ case DW_OP_deref_size:
+ element->type = e_dw_deref;
+ element->location.deref_size = (unsigned int short) op->number;
+ break;
+ case DW_OP_deref:
+ element->type = e_dw_deref;
+ element->location.deref_size = sizeof(void *);
+ break;
+ case DW_OP_constu:
+ element->type = e_dw_uconstant;
+ element->location.uconstant.bytes = 1;
+ element->location.uconstant.value = (unsigned long int) op->number;
+ break;
+ case DW_OP_consts:
+ element->type = e_dw_sconstant;
+ element->location.uconstant.bytes = 1;
+ element->location.uconstant.value = (unsigned long int) op->number;
+ break;
+
+ case DW_OP_const1u:
+ element->type = e_dw_uconstant;
+ element->location.uconstant.bytes = 1;
+ element->location.uconstant.value = (unsigned long int) op->number;
+ break;
+ case DW_OP_const2u:
+ element->type = e_dw_uconstant;
+ element->location.uconstant.bytes = 2;
+ element->location.uconstant.value = (unsigned long int) op->number;
+ break;
+ case DW_OP_const4u:
+ element->type = e_dw_uconstant;
+ element->location.uconstant.bytes = 4;
+ element->location.uconstant.value = (unsigned long int) op->number;
+ break;
+ case DW_OP_const8u:
+ element->type = e_dw_uconstant;
+ element->location.uconstant.bytes = 8;
+ element->location.uconstant.value = (unsigned long int) op->number;
+ break;
+
+ case DW_OP_const1s:
+ element->type = e_dw_sconstant;
+ element->location.uconstant.bytes = 1;
+ element->location.uconstant.value = (unsigned long int) op->number;
+ break;
+ case DW_OP_const2s:
+ element->type = e_dw_sconstant;
+ element->location.uconstant.bytes = 2;
+ element->location.uconstant.value = (unsigned long int) op->number;
+ break;
+ case DW_OP_const4s:
+ element->type = e_dw_sconstant;
+ element->location.uconstant.bytes = 4;
+ element->location.uconstant.value = (unsigned long int) op->number;
+ break;
+ case DW_OP_const8s:
+ element->type = e_dw_sconstant;
+ element->location.uconstant.bytes = 8;
+ element->location.uconstant.value = (unsigned long int) op->number;
+ break;
+ default:
+ element->type = e_dw_unsupported;
+ break;
+ }
+ return element;
+}
+
+/** \brief Convert libdw location expresion into native one */
+static dw_location_t MC_dwarf_get_expression(Dwarf_Op* expr, size_t len) {
+ dw_location_t loc = xbt_new0(s_dw_location_t, 1);
+ loc->type = e_dw_compose;
+ loc->location.compose = xbt_dynar_new(sizeof(dw_location_t), NULL);
+
+ int i;
+ for (i=0; i!=len; ++i) {
+ dw_location_t element = MC_dwarf_get_expression_element(expr+i);
+ if (element)
+ xbt_dynar_push(loc->location.compose, &element);
+ }
+
+ return loc;
+}
+
+static int mc_anonymous_variable_index = 0;
+
+static dw_variable_t MC_die_to_variable(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame) {
+ // Drop declaration:
+ if (MC_dwarf_attr_flag(die, DW_AT_declaration, false))
+ return NULL;
+
+ Dwarf_Attribute attr_location;
+ if (dwarf_attr(die, DW_AT_location, &attr_location)==NULL) {
+ // No location: do not add it ?
+ return NULL;
+ }
+
+ dw_variable_t variable = xbt_new0(s_dw_variable_t, 1);
+ variable->dwarf_offset = dwarf_dieoffset(die);
+ variable->global = frame == NULL; // Can be override base on DW_AT_location
+ variable->name = xbt_strdup(MC_dwarf_attr_string(die, DW_AT_name));
+ variable->type_origin = MC_dwarf_at_type(die);
+
+ int klass = MC_dwarf_form_get_class(dwarf_whatform(&attr_location));
+ switch (klass) {
+ case MC_DW_CLASS_EXPRLOC:
+ case MC_DW_CLASS_BLOCK:
+ // Location expression:
+ {
+ Dwarf_Op* expr;
+ size_t len;
+ if (dwarf_getlocation(&attr_location, &expr, &len)) {
+ xbt_die(
+ "Could not read location expression in DW_AT_location of variable <%p>%s",
+ (void*) variable->dwarf_offset, variable->name);
+ }
+
+ if (len==1 && expr[0].atom == DW_OP_addr) {
+ variable->global = 1;
+ Dwarf_Off offset = expr[0].number;
+ // TODO, Why is this different base on the object?
+ Dwarf_Off base = strcmp(info->file_name, xbt_binary_name) !=0 ? (Dwarf_Off) info->start_exec : 0;
+ variable->address = (void*) (base + offset);
+ } else {
+ variable->location = MC_dwarf_get_expression(expr, len);
+ }
+
+ break;
+ }
+ case MC_DW_CLASS_LOCLISTPTR:
+ case MC_DW_CLASS_CONSTANT:
+ // Reference to location list:
+ variable->location = MC_dwarf_get_location_list(info, die, &attr_location);
+ break;
+ default:
+ xbt_die("Unexpected calss 0x%x (%i) list for location in <%p>%s",
+ klass, klass, (void*) variable->dwarf_offset, variable->name);
+ }
+
+ // The current code needs a variable name,
+ // generate a fake one:
+ if(!variable->name) {
+ variable->name = bprintf("@anonymous#%i", mc_anonymous_variable_index++);
+ }
+
+ return variable;
+}
+
+static void MC_dwarf_handle_variable_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame) {
+ dw_variable_t variable = MC_die_to_variable(info, die, unit, frame);
+ if(variable==NULL)
+ return;
+ MC_dwarf_register_variable(info, frame, variable);
+}
+
+static void MC_dwarf_handle_subprogram_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t parent_frame) {
+ dw_frame_t frame = xbt_new0(s_dw_frame_t, 1);
+
+ frame->start = dwarf_dieoffset(die);
+
+ const char* name = MC_dwarf_at_linkage_name(die);
+ if (name==NULL)
+ name = MC_dwarf_attr_string(die, DW_AT_name);
+ frame->name = xbt_strdup(name);
+
+ // This is the base address for DWARF addresses.
+ // Relocated addresses are offset from this base address.
+ // See DWARF4 spec 7.5
+ void* base = info->flags & MC_OBJECT_INFO_EXECUTABLE ? 0 : MC_object_base_address(info);
+
+ // Variables are filled in the (recursive) call of MC_dwarf_handle_children:
+ frame->variables = xbt_dynar_new(sizeof(dw_variable_t), dw_variable_free_voidp);
+ frame->high_pc = ((char*) base) + MC_dwarf_attr_addr(die, DW_AT_high_pc);
+ frame->low_pc = ((char*) base) + MC_dwarf_attr_addr(die, DW_AT_low_pc);
+ frame->frame_base = MC_dwarf_at_location(info, die, DW_AT_frame_base);
+ frame->end = -1; // This one is now useless:
+
+ // Handle children:
+ MC_dwarf_handle_children(info, die, unit, frame);
+
+ // Register it:
+ xbt_dict_set(info->local_variables, frame->name, frame, NULL);
+}
+
+static void MC_dwarf_handle_children(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame) {
+ Dwarf_Die child;
+ int res;
+ for (res=dwarf_child(die, &child); res==0; res=dwarf_siblingof(&child,&child)) {
+ MC_dwarf_handle_die(info, &child, unit, frame);
+ }
+}
+
+static void MC_dwarf_handle_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame) {
+ int tag = dwarf_tag(die);
+ switch (tag) {
+ case DW_TAG_array_type:
+ case DW_TAG_class_type:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_typedef:
+ case DW_TAG_pointer_type:
+ case DW_TAG_string_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_subroutine_type:
+ case DW_TAG_union_type:
+ case DW_TAG_ptr_to_member_type:
+ case DW_TAG_set_type:
+ case DW_TAG_subrange_type:
+ case DW_TAG_base_type:
+ case DW_TAG_const_type:
+ case DW_TAG_file_type:
+ case DW_TAG_packed_type:
+ case DW_TAG_volatile_type:
+ case DW_TAG_restrict_type:
+ case DW_TAG_interface_type:
+ case DW_TAG_unspecified_type:
+ case DW_TAG_mutable_type:
+ case DW_TAG_shared_type:
+ MC_dwarf_handle_type_die(info, die, unit);
+ break;
+ case DW_TAG_subprogram:
+ MC_dwarf_handle_subprogram_die(info, die, unit, frame);
+ return;
+ // case DW_TAG_formal_parameter:
+ case DW_TAG_variable:
+ case DW_TAG_formal_parameter:
+ MC_dwarf_handle_variable_die(info, die, unit, frame);
+ break;
+ }
+
+ // Recursive processing of children DIE:
+ MC_dwarf_handle_children(info, die, unit, frame);
+}
+
+void MC_dwarf_get_variables(mc_object_info_t info) {
+ int fd = open(info->file_name, O_RDONLY);
+ if (fd<0) {
+ xbt_die("Could not open file %s", info->file_name);
+ }
+ Dwarf *dwarf = dwarf_begin(fd, DWARF_C_READ);
+ if (dwarf==NULL) {
+ xbt_die("Your program must be compiled with -g");
+ }
+
+ Dwarf_Off offset = 0;
+ Dwarf_Off next_offset = 0;
+ size_t length;
+ while (dwarf_nextcu (dwarf, offset, &next_offset, &length, NULL, NULL, NULL) == 0) {
+ Dwarf_Die die;
+
+ if(dwarf_offdie(dwarf, offset+length, &die)!=NULL) {
+
+ // Skip C++ for now (we will add support for it soon):
+ int lang = dwarf_srclang(&die);
+ if((lang==DW_LANG_C_plus_plus) || (lang==DW_LANG_ObjC_plus_plus)) {
+ offset = next_offset;
+ continue;
+ }
+
+ MC_dwarf_handle_die(info, &die, &die, NULL);
+ }
+ offset = next_offset;
+ }
+
+ dwarf_end(dwarf);
+ close(fd);
+}
--- /dev/null
+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";
--- /dev/null
+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";
#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"
int _sg_mc_checkpoint=0;
char* _sg_mc_property_file=NULL;
int _sg_mc_timeout=0;
+int _sg_mc_hash=0;
int _sg_mc_max_depth=1000;
int _sg_mc_visited=0;
char *_sg_mc_dot_output_file = NULL;
+int _sg_mc_comms_determinism=0;
int user_max_depth_reached = 0;
_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.");
_sg_mc_dot_output_file= xbt_cfg_get_string(_sg_cfg_set, name);
}
+void _mc_cfg_cb_comms_determinism(const char *name, int pos) {
+ if (_sg_cfg_init_status && !_sg_do_model_check) {
+ xbt_die("You are specifying a value to enable/disable the detection of determinism in the communications schemes after the initialization (through MSG_config?), but model-checking was not activated at config time (through --cfg=model-check:1). This won't work, sorry.");
+ }
+ _sg_mc_comms_determinism= xbt_cfg_get_boolean(_sg_cfg_set, name);
+}
+
/* MC global data structures */
mc_state_t mc_current_state = NULL;
char mc_replay_mode = FALSE;
xbt_automaton_t _mc_property_automaton = NULL;
/* Variables */
-xbt_dict_t mc_local_variables_libsimgrid = NULL;
-xbt_dict_t mc_local_variables_binary = NULL;
-xbt_dynar_t mc_global_variables_libsimgrid = NULL;
-xbt_dynar_t mc_global_variables_binary = NULL;
-xbt_dict_t mc_variables_type_libsimgrid = NULL;
-xbt_dict_t mc_variables_type_binary = NULL;
+mc_object_info_t mc_libsimgrid_info = NULL;
+mc_object_info_t mc_binary_info = NULL;
/* Ignore mechanism */
-xbt_dynar_t mc_stack_comparison_ignore;
-xbt_dynar_t mc_data_bss_comparison_ignore;
extern xbt_dynar_t mc_heap_comparison_ignore;
extern xbt_dynar_t stacks_areas;
xbt_free(e);
}
-static void dw_type_free(dw_type_t t){
+void dw_type_free(dw_type_t t){
xbt_free(t->name);
xbt_free(t->dw_type_id);
xbt_dynar_free(&(t->members));
dw_type_free((dw_type_t) * (void **) t);
}
-static void dw_variable_free(dw_variable_t v){
+void dw_variable_free(dw_variable_t v){
if(v){
xbt_free(v->name);
xbt_free(v->type_origin);
if(!v->global)
- dw_location_free(v->address.location);
+ dw_location_free(v->location);
xbt_free(v);
}
}
-static void dw_variable_free_voidp(void *t){
+void dw_variable_free_voidp(void *t){
dw_variable_free((dw_variable_t) * (void **) t);
}
+// ***** object_info
+
+mc_object_info_t MC_new_object_info(void) {
+ mc_object_info_t res = xbt_new0(s_mc_object_info_t, 1);
+ res->local_variables = xbt_dict_new_homogeneous(NULL);
+ res->global_variables = xbt_dynar_new(sizeof(dw_variable_t), dw_variable_free_voidp);
+ res->types = xbt_dict_new_homogeneous(NULL);
+ res->types_by_name = xbt_dict_new_homogeneous(NULL);
+ return res;
+}
+
+
+void MC_free_object_info(mc_object_info_t* info) {
+ xbt_free(&(*info)->file_name);
+ xbt_dict_free(&(*info)->local_variables);
+ xbt_dynar_free(&(*info)->global_variables);
+ xbt_dict_free(&(*info)->types);
+ xbt_dict_free(&(*info)->types_by_name);
+ xbt_free(info);
+ xbt_dynar_free(&(*info)->functions_index);
+ *info = NULL;
+}
+
+// ***** Helpers
+
+void* MC_object_base_address(mc_object_info_t info) {
+ void* result = info->start_exec;
+ if(info->start_rw!=NULL && result > (void*) info->start_rw) result = info->start_rw;
+ if(info->start_ro!=NULL && result > (void*) info->start_ro) result = info->start_ro;
+ return result;
+}
+
+// ***** Functions index
+
+static int MC_compare_frame_index_items(mc_function_index_item_t a, mc_function_index_item_t b) {
+ if(a->low_pc < b->low_pc)
+ return -1;
+ else if(a->low_pc == b->low_pc)
+ return 0;
+ else
+ return 1;
+}
+
+static void MC_make_functions_index(mc_object_info_t info) {
+ xbt_dynar_t index = xbt_dynar_new(sizeof(s_mc_function_index_item_t), NULL);
+
+ // Populate the array:
+ dw_frame_t frame = NULL;
+ xbt_dict_cursor_t cursor = NULL;
+ const char* name = NULL;
+ xbt_dict_foreach(info->local_variables, cursor, name, frame) {
+ if(frame->low_pc==NULL)
+ continue;
+ s_mc_function_index_item_t entry;
+ entry.low_pc = frame->low_pc;
+ entry.high_pc = frame->high_pc;
+ entry.function = frame;
+ xbt_dynar_push(index, &entry);
+ }
+
+ mc_function_index_item_t base = (mc_function_index_item_t) xbt_dynar_get_ptr(index, 0);
+
+ // Sort the array by low_pc:
+ qsort(base,
+ xbt_dynar_length(index),
+ sizeof(s_mc_function_index_item_t),
+ (int (*)(const void *, const void *))MC_compare_frame_index_items);
+
+ info->functions_index = index;
+}
+
+mc_object_info_t MC_ip_find_object_info(void* ip) {
+ mc_object_info_t infos[2] = { mc_binary_info, mc_libsimgrid_info };
+ size_t n = 2;
+ size_t i;
+ for(i=0; i!=n; ++i) {
+ if(ip >= (void*)infos[i]->start_exec && ip <= (void*)infos[i]->end_exec) {
+ return infos[i];
+ }
+ }
+ return NULL;
+}
+
+static dw_frame_t MC_find_function_by_ip_and_object(void* ip, mc_object_info_t info) {
+ xbt_dynar_t dynar = info->functions_index;
+ mc_function_index_item_t base = (mc_function_index_item_t) xbt_dynar_get_ptr(dynar, 0);
+ int i = 0;
+ int j = xbt_dynar_length(dynar) - 1;
+ while(j>=i) {
+ int k = i + ((j-i)/2);
+ if(ip < base[k].low_pc) {
+ j = k-1;
+ } else if(ip > base[k].high_pc) {
+ i = k+1;
+ } else {
+ return base[k].function;
+ }
+ }
+ return NULL;
+}
+
+dw_frame_t MC_find_function_by_ip(void* ip) {
+ mc_object_info_t info = MC_ip_find_object_info(ip);
+ if(info==NULL)
+ return NULL;
+ else
+ return MC_find_function_by_ip_and_object(ip, info);
+}
+
+static void MC_post_process_variables(mc_object_info_t info) {
+ unsigned cursor = 0;
+ dw_variable_t variable = NULL;
+ xbt_dynar_foreach(info->global_variables, cursor, variable) {
+ if(variable->type_origin) {
+ variable->type = xbt_dict_get_or_null(info->types, variable->type_origin);
+ }
+ }
+}
+
+static void MC_post_process_functions(mc_object_info_t info) {
+ xbt_dict_cursor_t cursor = NULL;
+ char* key = NULL;
+ dw_frame_t function = NULL;
+ xbt_dict_foreach(info->local_variables, cursor, key, function) {
+ unsigned cursor2 = 0;
+ dw_variable_t variable = NULL;
+ xbt_dynar_foreach(function->variables, cursor2, variable) {
+ if(variable->type_origin) {
+ variable->type = xbt_dict_get_or_null(info->types, variable->type_origin);
+ }
+ }
+ }
+}
+
+/** \brief Finds informations about a given shared object/executable */
+mc_object_info_t MC_find_object_info(memory_map_t maps, char* name, int executable) {
+ mc_object_info_t result = MC_new_object_info();
+ if(executable)
+ result->flags |= MC_OBJECT_INFO_EXECUTABLE;
+ result->file_name = xbt_strdup(name);
+ MC_find_object_address(maps, result);
+ MC_dwarf_get_variables(result);
+ MC_post_process_types(result);
+ MC_post_process_variables(result);
+ MC_post_process_functions(result);
+ MC_make_functions_index(result);
+ return result;
+}
+
/*************************************************************************/
static dw_location_t MC_dwarf_get_location(xbt_dict_t location_list, char *expr){
}
-static xbt_dict_t MC_dwarf_get_location_list(const char *elf_file){
-
- char *command = bprintf("objdump -Wo %s", elf_file);
-
- FILE *fp = popen(command, "r");
-
- if(fp == NULL){
- perror("popen for objdump failed");
- xbt_abort();
- }
-
- int debug = 0; /*Detect if the program has been compiled with -g */
-
- xbt_dict_t location_list = xbt_dict_new_homogeneous(NULL);
- char *line = NULL, *loc_expr = NULL;
- ssize_t read;
- size_t n = 0;
- int cursor_remove;
- xbt_dynar_t split = NULL;
-
- while ((read = xbt_getline(&line, &n, fp)) != -1) {
-
- /* Wipeout the new line character */
- line[read - 1] = '\0';
-
- xbt_str_trim(line, NULL);
-
- if(n == 0)
- continue;
-
- if(strlen(line) == 0)
- continue;
-
- if(debug == 0){
-
- if(strncmp(line, elf_file, strlen(elf_file)) == 0)
- continue;
-
- if(strncmp(line, "Contents", 8) == 0)
- continue;
-
- if(strncmp(line, "Offset", 6) == 0){
- debug = 1;
- continue;
- }
- }
-
- if(debug == 0){
- XBT_INFO("Your program must be compiled with -g");
- xbt_abort();
- }
-
- xbt_dynar_t loclist = xbt_dynar_new(sizeof(dw_location_entry_t), NULL);
-
- xbt_str_strip_spaces(line);
- split = xbt_str_split(line, " ");
-
- while(read != -1 && strcmp("<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);
-
- xbt_dynar_free(&split);
- free(loc_expr);
-
- read = xbt_getline(&line, &n, fp);
- if(read != -1){
- line[read - 1] = '\0';
- xbt_str_strip_spaces(line);
- split = xbt_str_split(line, " ");
- }
-
- }
-
-
- char *key = bprintf("%lu", strtoul((char *)xbt_dynar_get_as(split, 0, char *), NULL, 16));
- xbt_dict_set(location_list, key, loclist, NULL);
- xbt_free(key);
-
- xbt_dynar_free(&split);
-
- }
-
- xbt_free(line);
- xbt_free(command);
- pclose(fp);
-
- return location_list;
-}
-
+/** \brief Finds a frame (DW_TAG_subprogram) from an DWARF offset in the rangd of this subprogram
+ *
+ * The offset can be an offset of a child DW_TAG_variable.
+ */
static dw_frame_t MC_dwarf_get_frame_by_offset(xbt_dict_t all_variables, unsigned long int offset){
xbt_dict_cursor_t cursor = NULL;
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;
}
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;
}
+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);
}
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){
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);
}
MC_SET_RAW_MEM;
- if(mc_global_variables_libsimgrid){
+ xbt_assert(mc_libsimgrid_info, "MC subsystem not initialized");
unsigned int cursor = 0;
dw_variable_t current_var;
int start = 0;
- int end = xbt_dynar_length(mc_global_variables_libsimgrid) - 1;
+ int end = xbt_dynar_length(mc_libsimgrid_info->global_variables) - 1;
while(start <= end){
cursor = (start + end) /2;
- current_var = (dw_variable_t)xbt_dynar_get_as(mc_global_variables_libsimgrid, cursor, dw_variable_t);
+ current_var = (dw_variable_t)xbt_dynar_get_as(mc_libsimgrid_info->global_variables, cursor, dw_variable_t);
if(strcmp(current_var->name, name) == 0){
- xbt_dynar_remove_at(mc_global_variables_libsimgrid, cursor, NULL);
+ xbt_dynar_remove_at(mc_libsimgrid_info->global_variables, cursor, NULL);
start = 0;
- end = xbt_dynar_length(mc_global_variables_libsimgrid) - 1;
+ end = xbt_dynar_length(mc_libsimgrid_info->global_variables) - 1;
}else if(strcmp(current_var->name, name) < 0){
start = cursor + 1;
}else{
end = cursor - 1;
}
}
-
- }else{
-
- if(mc_data_bss_comparison_ignore == NULL)
- mc_data_bss_comparison_ignore = xbt_dynar_new(sizeof(mc_data_bss_ignore_variable_t), data_bss_ignore_variable_free_voidp);
-
- mc_data_bss_ignore_variable_t var = NULL;
- var = xbt_new0(s_mc_data_bss_ignore_variable_t, 1);
- var->name = strdup(name);
-
- if(xbt_dynar_is_empty(mc_data_bss_comparison_ignore)){
-
- xbt_dynar_insert_at(mc_data_bss_comparison_ignore, 0, &var);
-
- }else{
-
- unsigned int cursor = 0;
- int start = 0;
- int end = xbt_dynar_length(mc_data_bss_comparison_ignore) - 1;
- mc_data_bss_ignore_variable_t current_var = NULL;
-
- while(start <= end){
- cursor = (start + end) / 2;
- current_var = (mc_data_bss_ignore_variable_t)xbt_dynar_get_as(mc_data_bss_comparison_ignore, cursor, mc_data_bss_ignore_variable_t);
- if(strcmp(current_var->name, name) == 0){
- data_bss_ignore_variable_free(var);
- if(!raw_mem_set)
- MC_UNSET_RAW_MEM;
- return;
- }else if(strcmp(current_var->name, name) < 0){
- start = cursor + 1;
- }else{
- end = cursor - 1;
- }
- }
-
- if(strcmp(current_var->name, name) < 0)
- xbt_dynar_insert_at(mc_data_bss_comparison_ignore, cursor + 1, &var);
- else
- xbt_dynar_insert_at(mc_data_bss_comparison_ignore, cursor, &var);
-
- }
- }
if(!raw_mem_set)
MC_UNSET_RAW_MEM;
MC_SET_RAW_MEM;
- if(mc_local_variables_libsimgrid){
unsigned int cursor = 0;
dw_variable_t current_var;
int start, end;
xbt_dict_cursor_t dict_cursor;
char *current_frame_name;
dw_frame_t frame;
- xbt_dict_foreach(mc_local_variables_libsimgrid, dict_cursor, current_frame_name, frame){
+ xbt_dict_foreach(mc_libsimgrid_info->local_variables, dict_cursor, current_frame_name, frame){
start = 0;
end = xbt_dynar_length(frame->variables) - 1;
while(start <= end){
}
}
}
- xbt_dict_foreach(mc_local_variables_binary, dict_cursor, current_frame_name, frame){
+ xbt_dict_foreach(mc_binary_info->local_variables, dict_cursor, current_frame_name, frame){
start = 0;
end = xbt_dynar_length(frame->variables) - 1;
while(start <= end){
}
}
}else{
- xbt_dynar_t variables_list = ((dw_frame_t)xbt_dict_get_or_null(mc_local_variables_libsimgrid, frame_name))->variables;
+ xbt_dynar_t variables_list = ((dw_frame_t)xbt_dict_get_or_null(
+ mc_libsimgrid_info->local_variables, frame_name))->variables;
start = 0;
end = xbt_dynar_length(variables_list) - 1;
while(start <= end){
}
}
}
- }else{
-
- if(mc_stack_comparison_ignore == NULL)
- mc_stack_comparison_ignore = xbt_dynar_new(sizeof(mc_stack_ignore_variable_t), stack_ignore_variable_free_voidp);
-
- mc_stack_ignore_variable_t var = NULL;
- var = xbt_new0(s_mc_stack_ignore_variable_t, 1);
- var->var_name = strdup(var_name);
- var->frame = strdup(frame_name);
-
- if(xbt_dynar_is_empty(mc_stack_comparison_ignore)){
-
- xbt_dynar_insert_at(mc_stack_comparison_ignore, 0, &var);
-
- }else{
-
- unsigned int cursor = 0;
- int start = 0;
- int end = xbt_dynar_length(mc_stack_comparison_ignore) - 1;
- mc_stack_ignore_variable_t current_var = NULL;
-
- while(start <= end){
- cursor = (start + end) / 2;
- current_var = (mc_stack_ignore_variable_t)xbt_dynar_get_as(mc_stack_comparison_ignore, cursor, mc_stack_ignore_variable_t);
- if(strcmp(current_var->frame, frame_name) == 0){
- if(strcmp(current_var->var_name, var_name) == 0){
- stack_ignore_variable_free(var);
- if(!raw_mem_set)
- MC_UNSET_RAW_MEM;
- return;
- }else if(strcmp(current_var->var_name, var_name) < 0){
- start = cursor + 1;
- }else{
- end = cursor - 1;
- }
- }else if(strcmp(current_var->frame, frame_name) < 0){
- start = cursor + 1;
- }else{
- end = cursor - 1;
- }
- }
-
- if(strcmp(current_var->frame, frame_name) == 0){
- if(strcmp(current_var->var_name, var_name) < 0){
- xbt_dynar_insert_at(mc_stack_comparison_ignore, cursor + 1, &var);
- }else{
- xbt_dynar_insert_at(mc_stack_comparison_ignore, cursor, &var);
- }
- }else if(strcmp(current_var->frame, frame_name) < 0){
- xbt_dynar_insert_at(mc_stack_comparison_ignore, cursor + 1, &var);
- }else{
- xbt_dynar_insert_at(mc_stack_comparison_ignore, cursor, &var);
- }
- }
- }
if(!raw_mem_set)
MC_UNSET_RAW_MEM;
/******************************* Initialisation of MC *******************************/
/*********************************************************************************/
-static void MC_dump_ignored_local_variables(void){
-
- if(mc_stack_comparison_ignore == NULL || xbt_dynar_is_empty(mc_stack_comparison_ignore))
- return;
-
- unsigned int cursor = 0;
- mc_stack_ignore_variable_t current_var;
-
- xbt_dynar_foreach(mc_stack_comparison_ignore, cursor, current_var){
- MC_ignore_local_variable(current_var->var_name, current_var->frame);
+static void MC_post_process_object_info(mc_object_info_t info) {
+ mc_object_info_t other_info = info == mc_binary_info ? mc_libsimgrid_info : mc_binary_info;
+ xbt_dict_cursor_t cursor = NULL;
+ char* key = NULL;
+ dw_type_t type = NULL;
+ xbt_dict_foreach(info->types, cursor, key, type){
+ if(type->name && type->byte_size == 0) {
+ type->other_object_same_type = xbt_dict_get_or_null(other_info->types_by_name, type->name);
+ }
}
-
- xbt_dynar_free(&mc_stack_comparison_ignore);
- mc_stack_comparison_ignore = NULL;
-
}
-static void MC_dump_ignored_global_variables(void){
-
- if(mc_data_bss_comparison_ignore == NULL || xbt_dynar_is_empty(mc_data_bss_comparison_ignore))
- return;
+static void MC_init_debug_info(void) {
+ XBT_INFO("Get debug information ...");
- unsigned int cursor = 0;
- mc_data_bss_ignore_variable_t current_var;
+ memory_map_t maps = MC_get_memory_map();
- xbt_dynar_foreach(mc_data_bss_comparison_ignore, cursor, current_var){
- MC_ignore_global_variable(current_var->name);
- }
+ /* Get local variables for state equality detection */
+ mc_binary_info = MC_find_object_info(maps, xbt_binary_name, 1);
+ mc_libsimgrid_info = MC_find_object_info(maps, libsimgrid_path, 0);
- xbt_dynar_free(&mc_data_bss_comparison_ignore);
- mc_data_bss_comparison_ignore = NULL;
+ // Use information of the other objects:
+ MC_post_process_object_info(mc_binary_info);
+ MC_post_process_object_info(mc_libsimgrid_info);
+ MC_free_memory_map(maps);
+ XBT_INFO("Get debug information done !");
}
void MC_init(){
int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
-
+
compare = 0;
/* Initialize the data structures that must be persistent across every
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);
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));
}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;
}
/* 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();
void MC_exit(void)
{
xbt_free(mc_time);
+
MC_memory_exit();
//xbt_abort();
}
xbt_fifo_item_t item, start_item;
mc_state_t state;
smx_process_t process = NULL;
+ int comm_pattern = 0;
XBT_DEBUG("**** Begin Replay ****");
xbt_free(key);
}
}
+ if(_sg_mc_comms_determinism)
+ xbt_dynar_reset(communications_pattern);
MC_UNSET_RAW_MEM;
xbt_free(req_str);
}
}
-
+
+ if(_sg_mc_comms_determinism){
+ if(req->call == SIMCALL_COMM_ISEND)
+ comm_pattern = 1;
+ else if(req->call == SIMCALL_COMM_IRECV)
+ comm_pattern = 2;
+ }
+
SIMIX_simcall_pre(req, value);
+
+ if(_sg_mc_comms_determinism){
+ MC_SET_RAW_MEM;
+ if(comm_pattern != 0){
+ get_comm_pattern(communications_pattern, req, comm_pattern);
+ }
+ MC_UNSET_RAW_MEM;
+ comm_pattern = 0;
+ }
+
MC_wait_for_requests();
count++;
fprintf(dot_output, "}\n");
fclose(dot_output);
}
+ if(initial_state_safety != NULL && _sg_mc_comms_determinism){
+ XBT_INFO("Communication-deterministic : %s", !initial_state_safety->comm_deterministic ? "No" : "Yes");
+ XBT_INFO("Send-deterministic : %s", !initial_state_safety->send_deterministic ? "No" : "Yes");
+ }
MC_UNSET_RAW_MEM;
}
--- /dev/null
+/* 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){
+ // Simple case, hash this has binary:
+ case DW_TAG_base_type:
+ case DW_TAG_enumeration_type:
+ {
+ if(mc_ignored(address, 1))
+ return;
+ mc_hash_binary(hash, address, type->byte_size);
+ return;
+ }
+
+ case DW_TAG_array_type:
+ {
+ if(mc_ignored(address, type->byte_size))
+ return;
+
+ long element_count = type->element_count;
+ dw_type_t subtype = type->subtype;
+ if(subtype==NULL) {
+ XBT_DEBUG("Hash array without subtype");
+ return;
+ }
+ int i;
+ for(i=0; i!=element_count; ++i) {
+ XBT_DEBUG("Hash array element %i", i);
+ void* subaddress = ((char*)address)+i*subtype->byte_size;
+ mc_hash_value(hash, state, info, subaddress, subtype);
+ }
+ return;
+ }
+
+ // Get the raw type:
+ case DW_TAG_typedef:
+ case DW_TAG_volatile_type:
+ case DW_TAG_const_type:
+ case DW_TAG_restrict_type:
+ {
+ type = type->subtype;
+ if(type==NULL)
+ return;
+ else
+ goto top;
+ }
+
+ case DW_TAG_structure_type:
+ case DW_TAG_class_type:
+ {
+ if(mc_ignored(address, type->byte_size))
+ return;
+
+ unsigned int cursor = 0;
+ dw_type_t member;
+ xbt_dynar_foreach(type->members, cursor, member){
+ XBT_DEBUG("Hash struct member %s", member->name);
+ if(type->subtype==NULL)
+ return;
+ mc_hash_value(hash, state, info, ((char*)address) + member->offset, type->subtype);
+ }
+ return;
+ }
+
+ // Pointer, we hash a single value but it might be an array.
+ case DW_TAG_pointer_type:
+ case DW_TAG_reference_type:
+ case DW_TAG_rvalue_reference_type:
+ {
+ if(mc_ignored(address, 1))
+ return;
+
+ void* pointed = *(void**)address;
+ if(pointed==NULL) {
+ XBT_DEBUG("Hashed pinter is NULL");
+ return;
+ }
+
+ // Avoid loops:
+ if(mc_address_test(state->handled_addresses, pointed)) {
+ XBT_DEBUG("Hashed pointed data %p already hashed", pointed);
+ return;
+ }
+ mc_address_add(state->handled_addresses, pointed);
+
+ // Anything outside the R/W segments and the heap is not hashed:
+ bool valid_pointer = (pointed >= (void*) mc_binary_info->start_rw && pointed <= (void*) mc_binary_info->end_rw)
+ || (pointed >= (void*) mc_libsimgrid_info->start_rw && pointed <= (void*) mc_libsimgrid_info->end_rw)
+ || (pointed >= std_heap && pointed < (void*) ((const char*)std_heap + STD_HEAP_SIZE));
+ if(!valid_pointer) {
+ XBT_DEBUG("Hashed pointed data %p is in an ignored range", pointed);
+ return;
+ }
+
+ if(type->subtype==NULL) {
+ XBT_DEBUG("Missing type for %p (type=%s)", pointed, type->dw_type_id);
+ return;
+ }
+
+ address = pointed;
+ type = type->subtype;
+ goto top;
+ }
+
+ // Skip this:
+ case DW_TAG_union_type:
+ case DW_TAG_subroutine_type:
+ default:
+ return;
+ }
+}
+
+
+static void mc_hash_object_globals(mc_hash_t *hash, mc_hashing_state* state, mc_object_info_t info) {
+ unsigned int cursor = 0;
+ dw_variable_t variable;
+ xbt_dynar_foreach(info->global_variables, cursor, variable) {
+ XBT_DEBUG("Hash global variable %s", variable->name);
+
+ if(variable->type_origin == NULL) {
+ // Nothing
+ continue;
+ }
+
+ dw_type_t type = variable->type;
+ if(type==NULL) {
+ // Nothing
+ continue;
+ }
+
+ const char* address = variable->address;
+ bool valid_pointer = (address >= mc_binary_info->start_rw && address <= mc_binary_info->end_rw)
+ || (address >= mc_libsimgrid_info->start_rw && address <= mc_libsimgrid_info->end_rw)
+ || (address >= (const char*) std_heap && address < (const char *)std_heap + STD_HEAP_SIZE);
+ if(!valid_pointer) continue;
+
+ mc_hash_value(hash, state, info, variable->address, type);
+ }
+}
+
+static void mc_hash_stack_frame(
+ mc_hash_t *hash,
+ mc_object_info_t info, unw_cursor_t* unw_cursor, dw_frame_t frame, char* frame_pointer, mc_hashing_state* state
+ ) {
+
+ // return; // TEMP
+
+ unsigned int cursor = 0;
+ dw_variable_t variable;
+ xbt_dynar_foreach(frame->variables, cursor, variable){
+
+ if(variable->type_origin==NULL) {
+ XBT_DEBUG("Hash local variable %s without type", variable->name);
+ continue;
+ }
+ if(variable->location == NULL) {
+ XBT_DEBUG("Hash local variable %s without location", variable->name);
+ continue;
+ }
+
+ XBT_DEBUG("Hash local variable %s", variable->name);
+
+ void* variable_address = (void*) MC_dwarf_resolve_location(unw_cursor, variable->location, frame_pointer);
+
+ dw_type_t type = variable->type;
+ if(type==NULL) {
+ XBT_DEBUG("Hash local variable %s without loctypeation", variable->name);
+ continue;
+ }
+
+ mc_hash_value(hash, state, info, variable_address, type);
+ }
+}
+
+static void mc_hash_stack(mc_hash_t *hash, mc_snapshot_stack_t stack, mc_hashing_state* state) {
+
+ unsigned cursor = 0;
+ mc_stack_frame_t stack_frame;
+
+ xbt_dynar_foreach(stack->stack_frames, cursor, stack_frame) {
+
+ MC_HASH(*hash, stack_frame->ip);
+
+ mc_object_info_t info;
+ if(stack_frame->ip >= (unw_word_t) mc_libsimgrid_info->start_exec && stack_frame->ip < (unw_word_t) mc_libsimgrid_info->end_exec)
+ info = mc_libsimgrid_info;
+ else if(stack_frame->ip >= (unw_word_t) mc_binary_info->start_exec && stack_frame->ip < (unw_word_t) mc_binary_info->end_exec)
+ info = mc_binary_info;
+ else
+ continue;
+
+ mc_hash_stack_frame(hash, info, &(stack_frame->unw_cursor), stack_frame->frame, (void*)stack_frame->frame_base, state);
+
+ }
+}
+
+static void mc_hash_stacks(mc_hash_t *hash, mc_hashing_state* state, xbt_dynar_t stacks) {
+ unsigned int cursor = 0;
+ mc_snapshot_stack_t current_stack;
+
+ MC_HASH(*hash, xbt_dynar_length(stacks_areas));
+
+ int i=0;
+ xbt_dynar_foreach(stacks, cursor, current_stack){
+ XBT_DEBUG("Stack %i", i);
+ mc_hash_stack(hash, current_stack, state);
+ ++i;
+ }
+}
+
+uint64_t mc_hash_processes_state(int num_state, xbt_dynar_t stacks) {
+ XBT_DEBUG("START hash %i", num_state);
+
+ mc_hashing_state state;
+ mc_hash_state_init(&state);
+
+ mc_hash_t hash = MC_HASH_INIT;
+
+ MC_HASH(hash, xbt_swag_size(simix_global->process_list)); // process count
+ mc_hash_object_globals(&hash, &state, mc_binary_info);
+ // mc_hash_object_globals(&hash, &state, mc_libsimgrid_info);
+ mc_hash_stacks(&hash, &state, stacks);
+
+ mc_hash_state_destroy(&state);
+
+ XBT_DEBUG("END hash %i", num_state);
+ return hash;
+}
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);
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);
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)
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;
#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);
}
#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)*/
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{
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{
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 **********************************/
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;
//#define MC_DEBUG 1
#define MC_VERBOSE 1
-
/********************************** DPOR for safety property **************************************/
typedef enum {
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;
/********************************** Variables with DWARF **********************************/
-extern xbt_dict_t mc_local_variables_libsimgrid;
-extern xbt_dict_t mc_local_variables_binary;
-extern xbt_dynar_t mc_global_variables_libsimgrid;
-extern xbt_dynar_t mc_global_variables_binary;
-extern xbt_dict_t mc_variables_type_libsimgrid;
-extern xbt_dict_t mc_variables_type_binary;
+#define MC_OBJECT_INFO_EXECUTABLE 1
+
+struct s_mc_object_info {
+ size_t flags;
+ char* file_name;
+ char *start_exec, *end_exec; // Executable segment
+ char *start_rw, *end_rw; // Read-write segment
+ char *start_ro, *end_ro; // read-only segment
+ xbt_dict_t local_variables; // xbt_dict_t<frame_name, 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 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;
+
+void MC_find_object_address(memory_map_t maps, mc_object_info_t result);
+void MC_post_process_types(mc_object_info_t info);
typedef enum {
e_dw_loclist,
}s_dw_location_t, *dw_location_t;
typedef struct s_dw_location_entry{
- unsigned long lowpc;
- unsigned long highpc;
+ void* lowpc;
+ void* highpc;
dw_location_t location;
}s_dw_location_entry_t, *dw_location_entry_t;
typedef struct s_dw_variable{
+ Dwarf_Off dwarf_offset; /* Global offset of the field. */
int global;
char *name;
char *type_origin;
- union{
- dw_location_t location;
- void *address;
- }address;
+ dw_type_t type;
+
+ // Use either of:
+ dw_location_t location;
+ void* address;
+
}s_dw_variable_t, *dw_variable_t;
-typedef struct s_dw_frame{
+struct s_dw_frame{
char *name;
void *low_pc;
void *high_pc;
dw_location_t frame_base;
- xbt_dynar_t variables; /* Cannot use dict, there may be several variables with the same name (in different lexical blocks)*/
- unsigned long int start;
- unsigned long int end;
-}s_dw_frame_t, *dw_frame_t;
+ xbt_dynar_t /* <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 dw_type_free(dw_type_t t);
+void dw_variable_free(dw_variable_t v);
+void dw_variable_free_voidp(void *t);
+
+void MC_dwarf_register_global_variable(mc_object_info_t info, dw_variable_t variable);
+void MC_register_variable(mc_object_info_t info, dw_frame_t frame, dw_variable_t variable);
+void MC_dwarf_register_non_global_variable(mc_object_info_t info, dw_frame_t frame, dw_variable_t variable);
+void MC_dwarf_register_variable(mc_object_info_t info, dw_frame_t frame, dw_variable_t variable);
+void* MC_object_base_address(mc_object_info_t info);
+
+/********************************** DWARF **********************************/
+
+Dwarf_Off MC_dwarf_resolve_location(unw_cursor_t* c, dw_location_t location, void* frame_pointer_address);
+void* mc_find_frame_base(void* ip, dw_frame_t frame, unw_cursor_t* unw_cursor);
/********************************** Miscellaneous **********************************/
char *frame;
unsigned long ip;
char *name;
- char *type;
+ dw_type_t type;
void *address;
int region;
}s_local_variable_t, *local_variable_t;
+/********************************* Communications pattern ***************************/
+
+typedef struct s_mc_comm_pattern{
+ int num;
+ smx_action_t comm;
+ e_smx_comm_type_t type;
+ int completed;
+ unsigned long src_proc;
+ unsigned long dst_proc;
+ char *rdv;
+ size_t data_size;
+ void *data;
+ int matched_comm;
+}s_mc_comm_pattern_t, *mc_comm_pattern_t;
+
+extern xbt_dynar_t communications_pattern;
+
+void get_comm_pattern(xbt_dynar_t communications_pattern, smx_simcall_t request, int call);
+
+/* *********** Sets *********** */
+
+typedef struct s_mc_address_set *mc_address_set_t;
+
+mc_address_set_t mc_address_set_new();
+mc_address_set_t mc_address_set_free(mc_address_set_t* p);
+void mc_address_add(mc_address_set_t p, const void* value);
+bool mc_address_test(mc_address_set_t p, const void* value);
+
+/* *********** Hash *********** */
+
+/** \brief Hash the current state
+ * \param num_state number of states
+ * \param stacks stacks (mc_snapshot_stak_t) used fot the stack unwinding informations
+ * \result resulting hash
+ * */
+uint64_t mc_hash_processes_state(int num_state, xbt_dynar_t stacks);
+
#endif
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;
}
}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;
--- /dev/null
+/* 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();
+mc_address_set_t mc_address_set_free(mc_address_set_t* p);
+void mc_address_add(mc_address_set_t p, const void* value);
+bool mc_address_test(mc_address_set_t p, const void* value);
+
+mc_address_set_t mc_address_set_new() {
+ return new std::set<const void*>();
+}
+
+mc_address_set_t mc_address_set_free(mc_address_set_t* p) {
+ delete *p;
+ *p = NULL;
+}
+
+void mc_address_add(mc_address_set_t p, const void* value) {
+ p->insert(value);
+}
+
+bool mc_address_test(mc_address_set_t p, const void* value) {
+ return p->find(value) != p->end();
+}
+
+};
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];
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;
/* do stateful model-checking */
xbt_cfg_register(&_sg_cfg_set, "model-check/checkpoint",
"Specify the amount of steps between checkpoints during stateful model-checking (default: 0 => stateless verification). "
- "If value=on, one checkpoint is saved for each step => faster verification, but huge memory consumption; higher values are good compromises between speed and memory consumption.",
+ "If value=1, one checkpoint is saved for each step => faster verification, but huge memory consumption; higher values are good compromises between speed and memory consumption.",
xbt_cfgelm_int, 0, 1, _mc_cfg_cb_checkpoint, NULL);
xbt_cfg_setdefault_int(_sg_cfg_set, "model-check/checkpoint", 0);
xbt_cfgelm_string, 0, 1, _mc_cfg_cb_property, NULL);
xbt_cfg_setdefault_string(_sg_cfg_set, "model-check/property", "");
+ /* do determinism model-checking */
+ xbt_cfg_register(&_sg_cfg_set, "model-check/communications_determinism",
+ "Enable/disable the detection of determinism in the communications schemes",
+ xbt_cfgelm_boolean, 0, 1, _mc_cfg_cb_comms_determinism, NULL);
+ xbt_cfg_setdefault_boolean(_sg_cfg_set, "model-check/communications_determinism", "no");
+
/* Specify the kind of model-checking reduction */
xbt_cfg_register(&_sg_cfg_set, "model-check/reduction",
"Specify the kind of exploration reduction (either none or DPOR)",
xbt_cfgelm_boolean, 0, 1, _mc_cfg_cb_timeout, NULL);
xbt_cfg_setdefault_boolean(_sg_cfg_set, "model-check/timeout", "no");
+ /* Enable/disable global hash computation with model-checking */
+ xbt_cfg_register(&_sg_cfg_set, "model-check/hash",
+ "Enable/Disable state hash for state comparison",
+ xbt_cfgelm_boolean, 0, 1, _mc_cfg_cb_hash, NULL);
+ xbt_cfg_setdefault_boolean(_sg_cfg_set, "model-check/hash", "no");
+
/* Set max depth exploration */
xbt_cfg_register(&_sg_cfg_set, "model-check/max_depth",
"Specify the max depth of exploration (default : 1000)",
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)
#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 */
#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");
typedef char* type_name;
-__thread void *s_heap = NULL, *heapbase1 = NULL, *heapbase2 = NULL;
-__thread malloc_info *heapinfo1 = NULL, *heapinfo2 = NULL;
-__thread size_t heaplimit = 0, heapsize1 = 0, heapsize2 = 0;
-__thread xbt_dynar_t to_ignore1 = NULL, to_ignore2 = NULL;
-__thread heap_area_t **equals_to1, **equals_to2;
-__thread type_name **types1, **types2;
+struct s_mm_diff {
+ void *s_heap, *heapbase1, *heapbase2;
+ malloc_info *heapinfo1, *heapinfo2;
+ size_t heaplimit, heapsize1, heapsize2;
+ xbt_dynar_t to_ignore1, to_ignore2;
+ heap_area_t **equals_to1, **equals_to2;
+ type_name **types1, **types2;
+};
+
+__thread struct s_mm_diff* mm_diff_info = NULL;
/*********************************** Free functions ************************************/
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;
if(current_pair->fragment1 != -1){
- if(equals_to1[current_pair->block1][current_pair->fragment1] != NULL){
- previous_area = equals_to1[current_pair->block1][current_pair->fragment1];
- heap_area_free(equals_to2[previous_area->block][previous_area->fragment]);
- equals_to2[previous_area->block][previous_area->fragment] = NULL;
+ if(state->equals_to1[current_pair->block1][current_pair->fragment1] != NULL){
+ previous_area = state->equals_to1[current_pair->block1][current_pair->fragment1];
+ heap_area_free(state->equals_to2[previous_area->block][previous_area->fragment]);
+ state->equals_to2[previous_area->block][previous_area->fragment] = NULL;
heap_area_free(previous_area);
}
- if(equals_to2[current_pair->block2][current_pair->fragment2] != NULL){
- previous_area = equals_to2[current_pair->block2][current_pair->fragment2];
- heap_area_free(equals_to1[previous_area->block][previous_area->fragment]);
- equals_to1[previous_area->block][previous_area->fragment] = NULL;
+ if(state->equals_to2[current_pair->block2][current_pair->fragment2] != NULL){
+ previous_area = state->equals_to2[current_pair->block2][current_pair->fragment2];
+ heap_area_free(state->equals_to1[previous_area->block][previous_area->fragment]);
+ state->equals_to1[previous_area->block][previous_area->fragment] = NULL;
heap_area_free(previous_area);
}
- equals_to1[current_pair->block1][current_pair->fragment1] = new_heap_area(current_pair->block2, current_pair->fragment2);
- equals_to2[current_pair->block2][current_pair->fragment2] = new_heap_area(current_pair->block1, current_pair->fragment1);
+ state->equals_to1[current_pair->block1][current_pair->fragment1] = new_heap_area(current_pair->block2, current_pair->fragment2);
+ state->equals_to2[current_pair->block2][current_pair->fragment2] = new_heap_area(current_pair->block1, current_pair->fragment1);
}else{
- if(equals_to1[current_pair->block1][0] != NULL){
- previous_area = equals_to1[current_pair->block1][0];
- heap_area_free(equals_to2[previous_area->block][0]);
- equals_to2[previous_area->block][0] = NULL;
+ if(state->equals_to1[current_pair->block1][0] != NULL){
+ previous_area = state->equals_to1[current_pair->block1][0];
+ heap_area_free(state->equals_to2[previous_area->block][0]);
+ state->equals_to2[previous_area->block][0] = NULL;
heap_area_free(previous_area);
}
- if(equals_to2[current_pair->block2][0] != NULL){
- previous_area = equals_to2[current_pair->block2][0];
- heap_area_free(equals_to1[previous_area->block][0]);
- equals_to1[previous_area->block][0] = NULL;
+ if(state->equals_to2[current_pair->block2][0] != NULL){
+ previous_area = state->equals_to2[current_pair->block2][0];
+ heap_area_free(state->equals_to1[previous_area->block][0]);
+ state->equals_to1[previous_area->block][0] = NULL;
heap_area_free(previous_area);
}
- equals_to1[current_pair->block1][0] = new_heap_area(current_pair->block2, current_pair->fragment2);
- equals_to2[current_pair->block2][0] = new_heap_area(current_pair->block1, current_pair->fragment1);
+ state->equals_to1[current_pair->block1][0] = new_heap_area(current_pair->block2, current_pair->fragment2);
+ state->equals_to2[current_pair->block2][0] = new_heap_area(current_pair->block1, current_pair->fragment1);
}
}
}
-static int equal_blocks(int b1, int b2){
+static int equal_blocks(struct s_mm_diff *state, int b1, int b2){
- if(equals_to1[b1][0]->block == b2 && equals_to2[b2][0]->block == b1)
+ if(state->equals_to1[b1][0]->block == b2 && state->equals_to2[b2][0]->block == b1)
return 1;
return 0;
}
-static int equal_fragments(int b1, int f1, int b2, int f2){
+static int equal_fragments(struct s_mm_diff *state, int b1, int f1, int b2, int f2){
- if(equals_to1[b1][f1]->block == b2 && equals_to1[b1][f1]->fragment == f2 && equals_to2[b2][f2]->block == b1 && equals_to2[b2][f2]->fragment == f1)
+ if(state->equals_to1[b1][f1]->block == b2
+ && state->equals_to1[b1][f1]->fragment == f2
+ && state->equals_to2[b2][f2]->block == b1
+ && state->equals_to2[b2][f2]->fragment == f1)
return 1;
return 0;
}
int init_heap_information(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dynar_t i1, xbt_dynar_t i2){
+ if(mm_diff_info==NULL) {
+ mm_diff_info = xbt_new0(struct s_mm_diff, 1);
+ }
+ struct s_mm_diff *state = mm_diff_info;
- if((((struct mdesc *)heap1)->heaplimit != ((struct mdesc *)heap2)->heaplimit) || ((((struct mdesc *)heap1)->heapsize != ((struct mdesc *)heap2)->heapsize) ))
+ if((((struct mdesc *)heap1)->heaplimit != ((struct mdesc *)heap2)->heaplimit)
+ || ((((struct mdesc *)heap1)->heapsize != ((struct mdesc *)heap2)->heapsize) ))
return -1;
int i, j;
- heaplimit = ((struct mdesc *)heap1)->heaplimit;
+ state->heaplimit = ((struct mdesc *)heap1)->heaplimit;
- s_heap = (char *)mmalloc_get_current_heap() - STD_HEAP_SIZE - getpagesize();
+ state->s_heap = (char *)mmalloc_get_current_heap() - STD_HEAP_SIZE - getpagesize();
- heapbase1 = (char *)heap1 + BLOCKSIZE;
- heapbase2 = (char *)heap2 + BLOCKSIZE;
+ state->heapbase1 = (char *)heap1 + BLOCKSIZE;
+ state->heapbase2 = (char *)heap2 + BLOCKSIZE;
- heapinfo1 = (malloc_info *)((char *)heap1 + ((uintptr_t)((char *)((struct mdesc *)heap1)->heapinfo - (char *)s_heap)));
- heapinfo2 = (malloc_info *)((char *)heap2 + ((uintptr_t)((char *)((struct mdesc *)heap2)->heapinfo - (char *)s_heap)));
+ state->heapinfo1 = (malloc_info *)((char *)heap1 + ((uintptr_t)((char *)((struct mdesc *)heap1)->heapinfo - (char *)state->s_heap)));
+ state->heapinfo2 = (malloc_info *)((char *)heap2 + ((uintptr_t)((char *)((struct mdesc *)heap2)->heapinfo - (char *)state->s_heap)));
- heapsize1 = heap1->heapsize;
- heapsize2 = heap2->heapsize;
+ state->heapsize1 = heap1->heapsize;
+ state->heapsize2 = heap2->heapsize;
- to_ignore1 = i1;
- to_ignore2 = i2;
+ state->to_ignore1 = i1;
+ state-> to_ignore2 = i2;
- equals_to1 = malloc(heaplimit * sizeof(heap_area_t *));
- types1 = malloc(heaplimit * sizeof(type_name *));
- for(i=0; i<=heaplimit; i++){
- equals_to1[i] = malloc(MAX_FRAGMENT_PER_BLOCK * sizeof(heap_area_t));
- types1[i] = malloc(MAX_FRAGMENT_PER_BLOCK * sizeof(type_name));
+ state->equals_to1 = malloc(state->heaplimit * sizeof(heap_area_t *));
+ state->types1 = malloc(state->heaplimit * sizeof(type_name *));
+ for(i=0; i<=state->heaplimit; i++){
+ state->equals_to1[i] = malloc(MAX_FRAGMENT_PER_BLOCK * sizeof(heap_area_t));
+ state->types1[i] = malloc(MAX_FRAGMENT_PER_BLOCK * sizeof(type_name));
for(j=0; 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;
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;
+ xbt_free(state->types1[i][j]);
+ state->types1[i][j] = NULL;
+ xbt_free(state->types2[i][j]);
+ state->types2[i][j] = NULL;
}
- free(equals_to1[i]);
- free(equals_to2[i]);
- free(types1[i]);
- free(types2[i]);
+ free(state->equals_to1[i]);
+ free(state->equals_to2[i]);
+ free(state->types1[i]);
+ free(state->types2[i]);
}
- free(equals_to1);
- free(equals_to2);
- free(types1);
- free(types2);
+ free(state->equals_to1);
+ free(state->equals_to2);
+ free(state->types1);
+ free(state->types2);
- s_heap = NULL, heapbase1 = NULL, heapbase2 = NULL;
- heapinfo1 = NULL, heapinfo2 = NULL;
- heaplimit = 0, heapsize1 = 0, heapsize2 = 0;
- to_ignore1 = NULL, to_ignore2 = NULL;
- equals_to1 = NULL, equals_to2 = NULL;
- types1 = NULL, types2 = NULL;
+ state->s_heap = NULL, state->heapbase1 = NULL, state->heapbase2 = NULL;
+ state->heapinfo1 = NULL, state->heapinfo2 = NULL;
+ state->heaplimit = 0, state->heapsize1 = 0, state->heapsize2 = 0;
+ state->to_ignore1 = NULL, state->to_ignore2 = NULL;
+ state->equals_to1 = NULL, state->equals_to2 = NULL;
+ state->types1 = NULL, state->types2 = NULL;
}
-int mmalloc_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dict_t all_types, xbt_dict_t other_types){
+int mmalloc_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2, mc_object_info_t info, mc_object_info_t other_info){
+
+ struct s_mm_diff *state = mm_diff_info;
if(heap1 == NULL && heap2 == NULL){
XBT_DEBUG("Malloc descriptors null");
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;
}
res_compare = 0;
/* Try first to associate to same block in the other heap */
- if(heapinfo2[i1].type == heapinfo1[i1].type){
+ if(state->heapinfo2[i1].type == state->heapinfo1[i1].type){
- if(equals_to2[i1][0] == NULL){
+ if(state->equals_to2[i1][0] == NULL){
- addr_block2 = ((void*) (((ADDR2UINT(i1)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)s_heap)->heapbase));
+ addr_block2 = ((void*) (((ADDR2UINT(i1)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)state->s_heap)->heapbase));
- res_compare = compare_heap_area(addr_block1, addr_block2, NULL, all_types, other_types, NULL, 0);
+ res_compare = compare_heap_area(addr_block1, addr_block2, NULL, info, other_info, NULL, 0);
if(res_compare != 1){
- for(k=1; k < heapinfo2[i1].busy_block.size; k++)
- equals_to2[i1+k][0] = new_heap_area(i1, -1);
- for(k=1; k < heapinfo1[i1].busy_block.size; k++)
- equals_to1[i1+k][0] = new_heap_area(i1, -1);
+ for(k=1; k < state->heapinfo2[i1].busy_block.size; k++)
+ state->equals_to2[i1+k][0] = new_heap_area(i1, -1);
+ for(k=1; k < state->heapinfo1[i1].busy_block.size; k++)
+ state->equals_to1[i1+k][0] = new_heap_area(i1, -1);
equal = 1;
- i1 += heapinfo1[i1].busy_block.size;
+ i1 += state->heapinfo1[i1].busy_block.size;
}
xbt_dynar_reset(previous);
}
- while(i2 <= heaplimit && !equal){
+ while(i2 <= state->heaplimit && !equal){
- addr_block2 = ((void*) (((ADDR2UINT(i2)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)s_heap)->heapbase));
+ addr_block2 = ((void*) (((ADDR2UINT(i2)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)state->s_heap)->heapbase));
if(i2 == i1){
i2++;
continue;
}
- if(heapinfo2[i2].type != 0){
+ if(state->heapinfo2[i2].type != 0){
i2++;
continue;
}
- if(equals_to2[i2][0] != NULL){
+ if(state->equals_to2[i2][0] != NULL){
i2++;
continue;
}
- res_compare = compare_heap_area(addr_block1, addr_block2, NULL, all_types, other_types, NULL, 0);
+ res_compare = compare_heap_area(addr_block1, addr_block2, NULL, info, other_info, NULL, 0);
if(res_compare != 1 ){
- for(k=1; k < heapinfo2[i2].busy_block.size; k++)
- equals_to2[i2+k][0] = new_heap_area(i1, -1);
- for(k=1; k < heapinfo1[i1].busy_block.size; k++)
- equals_to1[i1+k][0] = new_heap_area(i2, -1);
+ for(k=1; k < state->heapinfo2[i2].busy_block.size; k++)
+ state->equals_to2[i2+k][0] = new_heap_area(i1, -1);
+ for(k=1; k < state->heapinfo1[i1].busy_block.size; k++)
+ state->equals_to1[i1+k][0] = new_heap_area(i2, -1);
equal = 1;
- i1 += heapinfo1[i1].busy_block.size;
+ i1 += state->heapinfo1[i1].busy_block.size;
}
xbt_dynar_reset(previous);
}
if(!equal){
- XBT_DEBUG("Block %zu not found (size_used = %zu, addr = %p)", i1, heapinfo1[i1].busy_block.busy_size, addr_block1);
- i1 = heaplimit + 1;
+ XBT_DEBUG("Block %zu not found (size_used = %zu, addr = %p)", i1, state->heapinfo1[i1].busy_block.busy_size, addr_block1);
+ i1 = state->heaplimit + 1;
nb_diff1++;
//i1++;
}
}else{ /* Fragmented block */
- for(j1=0; j1 < (size_t) (BLOCKSIZE >> heapinfo1[i1].type); j1++){
+ for(j1=0; j1 < (size_t) (BLOCKSIZE >> state->heapinfo1[i1].type); j1++){
- if(heapinfo1[i1].busy_frag.frag_size[j1] == -1) /* Free fragment */
+ if(state->heapinfo1[i1].busy_frag.frag_size[j1] == -1) /* Free fragment */
continue;
- if(equals_to1[i1][j1] != NULL)
+ if(state->equals_to1[i1][j1] != NULL)
continue;
- addr_frag1 = (void*) ((char *)addr_block1 + (j1 << heapinfo1[i1].type));
+ addr_frag1 = (void*) ((char *)addr_block1 + (j1 << state->heapinfo1[i1].type));
i2 = 1;
equal = 0;
/* Try first to associate to same fragment in the other heap */
- if(heapinfo2[i1].type == heapinfo1[i1].type){
+ if(state->heapinfo2[i1].type == state->heapinfo1[i1].type){
- if(equals_to2[i1][j1] == NULL){
+ if(state->equals_to2[i1][j1] == NULL){
- addr_block2 = ((void*) (((ADDR2UINT(i1)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)s_heap)->heapbase));
- addr_frag2 = (void*) ((char *)addr_block2 + (j1 << ((xbt_mheap_t)s_heap)->heapinfo[i1].type));
+ addr_block2 = ((void*) (((ADDR2UINT(i1)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)state->s_heap)->heapbase));
+ addr_frag2 = (void*) ((char *)addr_block2 + (j1 << ((xbt_mheap_t)state->s_heap)->heapinfo[i1].type));
- res_compare = compare_heap_area(addr_frag1, addr_frag2, NULL, all_types, other_types, NULL, 0);
+ res_compare = compare_heap_area(addr_frag1, addr_frag2, NULL, info, other_info, NULL, 0);
if(res_compare != 1)
equal = 1;
}
- while(i2 <= heaplimit && !equal){
+ while(i2 <= state->heaplimit && !equal){
- if(heapinfo2[i2].type <= 0){
+ if(state->heapinfo2[i2].type <= 0){
i2++;
continue;
}
- for(j2=0; j2 < (size_t) (BLOCKSIZE >> heapinfo2[i2].type); j2++){
+ for(j2=0; j2 < (size_t) (BLOCKSIZE >> state->heapinfo2[i2].type); j2++){
if(i2 == i1 && j2 == j1)
continue;
- if(equals_to2[i2][j2] != NULL)
+ if(state->equals_to2[i2][j2] != NULL)
continue;
- addr_block2 = ((void*) (((ADDR2UINT(i2)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)s_heap)->heapbase));
- addr_frag2 = (void*) ((char *)addr_block2 + (j2 <<((xbt_mheap_t)s_heap)->heapinfo[i2].type));
+ addr_block2 = ((void*) (((ADDR2UINT(i2)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)state->s_heap)->heapbase));
+ addr_frag2 = (void*) ((char *)addr_block2 + (j2 <<((xbt_mheap_t)state->s_heap)->heapinfo[i2].type));
- res_compare = compare_heap_area(addr_frag1, addr_frag2, NULL, all_types, other_types, NULL, 0);
+ res_compare = compare_heap_area(addr_frag1, addr_frag2, NULL, info, other_info, NULL, 0);
if(res_compare != 1){
equal = 1;
}
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;
}
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++;
}
}
}
- 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++;
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++;
}
}
}
- 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++;
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);
return ((nb_diff1 > 0) || (nb_diff2 > 0));
}
-static int compare_heap_area_without_type(void *real_area1, void *real_area2, void *area1, void *area2, xbt_dynar_t previous, xbt_dict_t all_types, xbt_dict_t other_types, int size, int check_ignore){
+static int compare_heap_area_without_type(struct s_mm_diff *state, void *real_area1, void *real_area2, void *area1, void *area2, xbt_dynar_t previous, mc_object_info_t info, mc_object_info_t other_info, int size, int check_ignore){
int i = 0;
void *addr_pointed1, *addr_pointed2;
- int pointer_align, ignore1, ignore2, res_compare;
+ int pointer_align, res_compare;
+ ssize_t ignore1, ignore2;
while(i<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;
if(addr_pointed1 > maestro_stack_start && addr_pointed1 < maestro_stack_end && addr_pointed2 > maestro_stack_start && addr_pointed2 < maestro_stack_end){
i = pointer_align + sizeof(void *);
continue;
- }else if((addr_pointed1 > s_heap) && ((char *)addr_pointed1 < (char *)s_heap + STD_HEAP_SIZE)
- && (addr_pointed2 > s_heap) && ((char *)addr_pointed2 < (char *)s_heap + STD_HEAP_SIZE)){
- res_compare = compare_heap_area(addr_pointed1, addr_pointed2, previous, all_types, other_types, NULL, 0);
+ }else if((addr_pointed1 > state->s_heap) && ((char *)addr_pointed1 < (char *)state->s_heap + STD_HEAP_SIZE)
+ && (addr_pointed2 > state->s_heap) && ((char *)addr_pointed2 < (char *)state->s_heap + STD_HEAP_SIZE)){
+ res_compare = compare_heap_area(addr_pointed1, addr_pointed2, previous, info, other_info, NULL, 0);
if(res_compare == 1){
return res_compare;
}
}
-
-static int compare_heap_area_with_type(void *real_area1, void *real_area2, void *area1, void *area2,
- xbt_dynar_t previous, xbt_dict_t all_types, xbt_dict_t other_types, char *type_id,
+// area_size is either a byte_size or an elements_count?&
+static int compare_heap_area_with_type(struct s_mm_diff *state, void *real_area1, void *real_area2, void *area1, void *area2,
+ xbt_dynar_t previous, mc_object_info_t info, mc_object_info_t other_info, char *type_id,
int area_size, int check_ignore, int pointer_level){
if(is_stack(real_area1) && is_stack(real_area2))
return 0;
- size_t ignore1, ignore2;
+ ssize_t ignore1, ignore2;
- if((check_ignore > 0) && ((ignore1 = heap_comparison_ignore_size(to_ignore1, real_area1)) > 0) && ((ignore2 = heap_comparison_ignore_size(to_ignore2, real_area2)) == ignore1)){
+ if((check_ignore > 0) && ((ignore1 = heap_comparison_ignore_size(state->to_ignore1, real_area1)) > 0) && ((ignore2 = heap_comparison_ignore_size(state->to_ignore2, real_area2)) == ignore1)){
return 0;
}
- dw_type_t type = xbt_dict_get_or_null(all_types, type_id);
+ dw_type_t type = xbt_dict_get_or_null(info->types, type_id);
dw_type_t subtype, subsubtype;
int res, elm_size, i, switch_types = 0;
unsigned int cursor = 0;
dw_type_t member;
void *addr_pointed1, *addr_pointed2;;
- char *type_desc;
switch(type->type){
- case e_dw_base_type:
- if(strcmp(type->name, "char") == 0){ /* String, hence random (arbitrary ?) size */
+ case DW_TAG_base_type:
+ if(type->name!=NULL && strcmp(type->name, "char") == 0){ /* String, hence random (arbitrary ?) size */
if(real_area1 == real_area2)
return -1;
else
return (memcmp(area1, area2, area_size) != 0);
}else{
- if(area_size != -1 && type->size != area_size)
+ if(area_size != -1 && type->byte_size != area_size)
return -1;
else{
- return (memcmp(area1, area2, type->size) != 0);
+ return (memcmp(area1, area2, type->byte_size) != 0);
}
}
break;
- case e_dw_enumeration_type:
- if(area_size != -1 && type->size != area_size)
+ case DW_TAG_enumeration_type:
+ if(area_size != -1 && type->byte_size != area_size)
return -1;
else
- return (memcmp(area1, area2, type->size) != 0);
- break;
- case e_dw_typedef:
- return compare_heap_area_with_type(real_area1, real_area2, area1, area2, previous, all_types, other_types, type->dw_type_id, area_size, check_ignore, pointer_level);
+ return (memcmp(area1, area2, type->byte_size) != 0);
break;
- case e_dw_const_type:
- return 0;
+ case DW_TAG_typedef:
+ case DW_TAG_const_type:
+ case DW_TAG_volatile_type:
+ return compare_heap_area_with_type(state, real_area1, real_area2, area1, area2, previous, info, other_info, type->dw_type_id, area_size, check_ignore, pointer_level);
break;
- case e_dw_array_type:
- subtype = xbt_dict_get_or_null(all_types, type->dw_type_id);
+ case DW_TAG_array_type:
+ subtype = xbt_dict_get_or_null(info->types, type->dw_type_id);
switch(subtype->type){
- case e_dw_base_type:
- case e_dw_enumeration_type:
- case e_dw_pointer_type:
- case e_dw_structure_type:
- case e_dw_union_type:
- if(subtype->size == 0){ /*declaration of the type, need the complete description */
- type_desc = get_type_description(all_types, subtype->name);
- if(type_desc){
- subtype = xbt_dict_get_or_null(all_types, type_desc);
- }else{
- subtype = xbt_dict_get_or_null(other_types, get_type_description(other_types, subtype->name));
+ case DW_TAG_base_type:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_pointer_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ if(subtype->byte_size == 0){ /*declaration of the type, need the complete description */
+ subtype = xbt_dict_get_or_null(other_info->types_by_name, subtype->name);
switch_types = 1;
- }
}
- elm_size = subtype->size;
+ elm_size = subtype->byte_size;
break;
- case e_dw_typedef:
- case e_dw_volatile_type:
- subsubtype = xbt_dict_get_or_null(all_types, subtype->dw_type_id);
- if(subsubtype->size == 0){ /*declaration of the type, need the complete description */
- type_desc = get_type_description(all_types, subsubtype->name);
- if(type_desc){
- subsubtype = xbt_dict_get_or_null(all_types, type_desc);
- }else{
- subsubtype = xbt_dict_get_or_null(other_types, get_type_description(other_types, subtype->name));
+ // TODO, just remove the type indirection?
+ case DW_TAG_const_type:
+ case DW_TAG_typedef:
+ case DW_TAG_volatile_type:
+ subsubtype = subtype->subtype;
+ if(subsubtype->byte_size == 0){ /*declaration of the type, need the complete description */
+ subsubtype = xbt_dict_get_or_null(other_info->types_by_name, subtype->name);
switch_types = 1;
- }
}
- elm_size = subsubtype->size;
+ elm_size = subsubtype->byte_size;
break;
default :
return 0;
break;
}
- for(i=0; i<type->size; i++){
+ for(i=0; i<type->element_count; i++){
+ // TODO, add support for variable stride (DW_AT_byte_stride)
if(switch_types)
- res = compare_heap_area_with_type((char *)real_area1 + (i*elm_size), (char *)real_area2 + (i*elm_size), (char *)area1 + (i*elm_size), (char *)area2 + (i*elm_size), previous, other_types, all_types, type->dw_type_id, type->size, check_ignore, pointer_level);
+ res = compare_heap_area_with_type(state, (char *)real_area1 + (i*elm_size), (char *)real_area2 + (i*elm_size), (char *)area1 + (i*elm_size), (char *)area2 + (i*elm_size), previous, other_info, info, type->dw_type_id, subtype->byte_size, check_ignore, pointer_level);
else
- res = compare_heap_area_with_type((char *)real_area1 + (i*elm_size), (char *)real_area2 + (i*elm_size), (char *)area1 + (i*elm_size), (char *)area2 + (i*elm_size), previous, all_types, other_types, type->dw_type_id, type->size, check_ignore, pointer_level);
+ res = compare_heap_area_with_type(state, (char *)real_area1 + (i*elm_size), (char *)real_area2 + (i*elm_size), (char *)area1 + (i*elm_size), (char *)area2 + (i*elm_size), previous, info, other_info, type->dw_type_id, subtype->byte_size, check_ignore, pointer_level);
if(res == 1)
return res;
}
break;
- case e_dw_pointer_type:
- if(type->dw_type_id && ((dw_type_t)xbt_dict_get_or_null(all_types, type->dw_type_id))->type == e_dw_subroutine_type){
+ case DW_TAG_pointer_type:
+ if(type->dw_type_id && ((dw_type_t)xbt_dict_get_or_null(info->types, type->dw_type_id))->type == DW_TAG_subroutine_type){
addr_pointed1 = *((void **)(area1));
addr_pointed2 = *((void **)(area2));
return (addr_pointed1 != addr_pointed2);;
for(i=0; i<(area_size/sizeof(void *)); i++){
addr_pointed1 = *((void **)((char *)area1 + (i*sizeof(void *))));
addr_pointed2 = *((void **)((char *)area2 + (i*sizeof(void *))));
- if(addr_pointed1 > s_heap && (char *)addr_pointed1 < (char*) s_heap + STD_HEAP_SIZE && addr_pointed2 > s_heap && (char *)addr_pointed2 < (char*) s_heap + STD_HEAP_SIZE)
- res = compare_heap_area(addr_pointed1, addr_pointed2, previous, all_types, other_types, type->dw_type_id, pointer_level);
+ if(addr_pointed1 > state->s_heap && (char *)addr_pointed1 < (char*) state->s_heap + STD_HEAP_SIZE && addr_pointed2 > state->s_heap && (char *)addr_pointed2 < (char*) state->s_heap + STD_HEAP_SIZE)
+ res = compare_heap_area(addr_pointed1, addr_pointed2, previous, info, other_info, type->dw_type_id, pointer_level);
else
res = (addr_pointed1 != addr_pointed2);
if(res == 1)
}else{
addr_pointed1 = *((void **)(area1));
addr_pointed2 = *((void **)(area2));
- if(addr_pointed1 > s_heap && (char *)addr_pointed1 < (char*) s_heap + STD_HEAP_SIZE && addr_pointed2 > s_heap && (char *)addr_pointed2 < (char*) s_heap + STD_HEAP_SIZE)
- return compare_heap_area(addr_pointed1, addr_pointed2, previous, all_types, other_types, type->dw_type_id, pointer_level);
+ if(addr_pointed1 > state->s_heap && (char *)addr_pointed1 < (char*) state->s_heap + STD_HEAP_SIZE && addr_pointed2 > state->s_heap && (char *)addr_pointed2 < (char*) state->s_heap + STD_HEAP_SIZE)
+ return compare_heap_area(addr_pointed1, addr_pointed2, previous, info, other_info, type->dw_type_id, pointer_level);
else
return (addr_pointed1 != addr_pointed2);
}
}
break;
- case e_dw_structure_type:
- if(type->size == 0){ /*declaration of the structure, need the complete description */
- type_desc = get_type_description(all_types, type->name);
- if(type_desc){
- type = xbt_dict_get_or_null(all_types, type_desc);
+ case DW_TAG_structure_type:
+ if(type->byte_size == 0){ /*declaration of the structure, need the complete description */
+ dw_type_t full_type = xbt_dict_get_or_null(info->types_by_name, type->name);
+ if(full_type){
+ type = full_type;
}else{
- type = xbt_dict_get_or_null(other_types, get_type_description(other_types, type->name));
+ type = xbt_dict_get_or_null(other_info->types_by_name, type->name);
switch_types = 1;
}
}
- if(area_size != -1 && type->size != area_size){
- if(area_size>type->size && area_size%type->size == 0){
- for(i=0; i<(area_size/type->size); i++){
+ if(area_size != -1 && type->byte_size != area_size){
+ if(area_size>type->byte_size && area_size%type->byte_size == 0){
+ for(i=0; i<(area_size/type->byte_size); i++){
if(switch_types)
- res = compare_heap_area_with_type((char *)real_area1 + (i*type->size), (char *)real_area2 + (i*type->size), (char *)area1 + (i*type->size), (char *)area2 + (i*type->size), previous, other_types, all_types, type_id, -1, check_ignore, 0);
+ res = compare_heap_area_with_type(state, (char *)real_area1 + (i*type->byte_size), (char *)real_area2 + (i*type->byte_size), (char *)area1 + (i*type->byte_size), (char *)area2 + (i*type->byte_size), previous, other_info, info, type_id, -1, check_ignore, 0);
else
- res = compare_heap_area_with_type((char *)real_area1 + (i*type->size), (char *)real_area2 + (i*type->size), (char *)area1 + (i*type->size), (char *)area2 + (i*type->size), previous, all_types, other_types, type_id, -1, check_ignore, 0);
+ res = compare_heap_area_with_type(state, (char *)real_area1 + (i*type->byte_size), (char *)real_area2 + (i*type->byte_size), (char *)area1 + (i*type->byte_size), (char *)area2 + (i*type->byte_size), previous, info, other_info, type_id, -1, check_ignore, 0);
if(res == 1)
return res;
}
cursor = 0;
xbt_dynar_foreach(type->members, cursor, member){
if(switch_types)
- res = compare_heap_area_with_type((char *)real_area1 + member->offset, (char *)real_area2 + member->offset, (char *)area1 + member->offset, (char *)area2 + member->offset, previous, other_types, all_types, member->dw_type_id, -1, check_ignore, 0);
+ res = compare_heap_area_with_type(state, (char *)real_area1 + member->offset, (char *)real_area2 + member->offset, (char *)area1 + member->offset, (char *)area2 + member->offset, previous, other_info, info, member->dw_type_id, -1, check_ignore, 0);
else
- res = compare_heap_area_with_type((char *)real_area1 + member->offset, (char *)real_area2 + member->offset, (char *)area1 + member->offset, (char *)area2 + member->offset, previous, all_types, other_types, member->dw_type_id, -1, check_ignore, 0);
+ res = compare_heap_area_with_type(state, (char *)real_area1 + member->offset, (char *)real_area2 + member->offset, (char *)area1 + member->offset, (char *)area2 + member->offset, previous, info, other_info, member->dw_type_id, -1, check_ignore, 0);
if(res == 1){
return res;
}
}
}
break;
- case e_dw_union_type:
- return compare_heap_area_without_type(real_area1, real_area2, area1, area2, previous, all_types, other_types, type->size, check_ignore);
- break;
- case e_dw_volatile_type:
- return compare_heap_area_with_type(real_area1, real_area2, area1, area2, previous, all_types, other_types, type->dw_type_id, area_size, check_ignore, pointer_level);
+ case DW_TAG_union_type:
+ return compare_heap_area_without_type(state, real_area1, real_area2, area1, area2, previous, info, other_info, type->byte_size, check_ignore);
break;
default:
break;
}
-static char* get_offset_type(char* type_id, int offset, xbt_dict_t all_types, xbt_dict_t other_types, int area_size, int *switch_type){
- dw_type_t type = xbt_dict_get_or_null(all_types, type_id);
+static char* get_offset_type(char* type_id, int offset, mc_object_info_t info, mc_object_info_t other_info, int area_size, int *switch_type){
+ dw_type_t type = xbt_dict_get_or_null(info->types, type_id);
if(type == NULL){
- type = xbt_dict_get_or_null(other_types, type_id);
+ type = xbt_dict_get_or_null(other_info->types, type_id);
*switch_type = 1;
}
- char* type_desc;
switch(type->type){
- case e_dw_structure_type :
- if(type->size == 0){ /*declaration of the structure, need the complete description */
+ case DW_TAG_structure_type :
+ if(type->byte_size == 0){ /*declaration of the structure, need the complete description */
if(*switch_type == 0){
- type_desc = get_type_description(all_types, type->name);
- if(type_desc){
- type = xbt_dict_get_or_null(all_types, type_desc);
+ dw_type_t full_type = xbt_dict_get_or_null(info->types_by_name, type->name);
+ if(full_type){
+ type = full_type;
}else{
- type = xbt_dict_get_or_null(other_types, get_type_description(other_types, type->name));
+ type = xbt_dict_get_or_null(other_info->types_by_name, type->name);
*switch_type = 1;
}
}else{
- type_desc = get_type_description(other_types, type->name);
- if(type_desc){
- type = xbt_dict_get_or_null(other_types, type_desc);
+ dw_type_t full_type = xbt_dict_get_or_null(other_info->types_by_name, type->name);
+ if(full_type){
+ type = full_type;
}else{
- type = xbt_dict_get_or_null(all_types, get_type_description(other_types, type->name));
+ type = xbt_dict_get_or_null(info->types_by_name, type->name);
*switch_type = 0;
}
}
}
- if(area_size != -1 && type->size != area_size){
- if(area_size>type->size && area_size%type->size == 0)
+ if(area_size != -1 && type->byte_size != area_size){
+ if(area_size>type->byte_size && area_size%type->byte_size == 0)
return type_id;
else
return NULL;
}
}
-int compare_heap_area(void *area1, void* area2, xbt_dynar_t previous, xbt_dict_t all_types, xbt_dict_t other_types, char *type_id, int pointer_level){
+int compare_heap_area(void *area1, void* area2, xbt_dynar_t previous, mc_object_info_t info, mc_object_info_t other_info, char *type_id, int pointer_level){
+
+ struct s_mm_diff* state = mm_diff_info;
int res_compare;
ssize_t block1, frag1, block2, frag2;
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;
match_pairs = 1;
}
- block1 = ((char*)area1 - (char*)((xbt_mheap_t)s_heap)->heapbase) / BLOCKSIZE + 1;
- block2 = ((char*)area2 - (char*)((xbt_mheap_t)s_heap)->heapbase) / BLOCKSIZE + 1;
+ block1 = ((char*)area1 - (char*)((xbt_mheap_t)state->s_heap)->heapbase) / BLOCKSIZE + 1;
+ block2 = ((char*)area2 - (char*)((xbt_mheap_t)state->s_heap)->heapbase) / BLOCKSIZE + 1;
if(is_block_stack((int)block1) && is_block_stack((int)block2)){
add_heap_area_pair(previous, block1, -1, block2, -1);
if(match_pairs){
- match_equals(previous);
+ match_equals(state, previous);
xbt_dynar_free(&previous);
}
return 0;
}
- if(((char *)area1 < (char*)((xbt_mheap_t)s_heap)->heapbase) || (block1 > heapsize1) || (block1 < 1) || ((char *)area2 < (char*)((xbt_mheap_t)s_heap)->heapbase) || (block2 > heapsize2) || (block2 < 1)){
+ if(((char *)area1 < (char*)((xbt_mheap_t)state->s_heap)->heapbase) || (block1 > state->heapsize1) || (block1 < 1) || ((char *)area2 < (char*)((xbt_mheap_t)state->s_heap)->heapbase) || (block2 > state->heapsize2) || (block2 < 1)){
if(match_pairs){
xbt_dynar_free(&previous);
}
return 1;
}
- addr_block1 = ((void*) (((ADDR2UINT(block1)) - 1) * BLOCKSIZE + (char*)heapbase1));
- addr_block2 = ((void*) (((ADDR2UINT(block2)) - 1) * BLOCKSIZE + (char*)heapbase2));
+ addr_block1 = ((void*) (((ADDR2UINT(block1)) - 1) * BLOCKSIZE + (char*)state->heapbase1));
+ addr_block2 = ((void*) (((ADDR2UINT(block2)) - 1) * BLOCKSIZE + (char*)state->heapbase2));
- real_addr_block1 = ((void*) (((ADDR2UINT(block1)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)s_heap)->heapbase));
- real_addr_block2 = ((void*) (((ADDR2UINT(block2)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)s_heap)->heapbase));
+ real_addr_block1 = ((void*) (((ADDR2UINT(block1)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)state->s_heap)->heapbase));
+ real_addr_block2 = ((void*) (((ADDR2UINT(block2)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)state->s_heap)->heapbase));
if(type_id){
- type = xbt_dict_get_or_null(all_types, type_id);
- if(type->size == 0){
- if(type->dw_type_id == NULL){
- type_desc = get_type_description(all_types, type->name);
- if(type_desc)
- type = xbt_dict_get_or_null(all_types, type_desc);
+ type = xbt_dict_get_or_null(info->types, type_id);
+ if(type->byte_size == 0){
+ if(type->subtype == NULL){
+ dw_type_t full_type = xbt_dict_get_or_null(info->types_by_name, type->name);
+ if(full_type)
+ type = full_type;
else
- type = xbt_dict_get_or_null(other_types, get_type_description(other_types, type->name));
+ type = xbt_dict_get_or_null(other_info->types_by_name, type->name);
}else{
- type = xbt_dict_get_or_null(all_types, type->dw_type_id);
+ type = type->subtype;
}
}
- if((type->type == e_dw_pointer_type) || ((type->type == e_dw_base_type) && (!strcmp(type->name, "char"))))
+ if((type->byte_size == DW_TAG_pointer_type) || ((type->type == DW_TAG_base_type) && type->name!=NULL && (!strcmp(type->name, "char"))))
type_size = -1;
else
- type_size = type->size;
+ type_size = type->byte_size;
}
- if((heapinfo1[block1].type == -1) && (heapinfo2[block2].type == -1)){ /* Free block */
+ if((state->heapinfo1[block1].type == -1) && (state->heapinfo2[block2].type == -1)){ /* Free block */
if(match_pairs){
- match_equals(previous);
+ match_equals(state, previous);
xbt_dynar_free(&previous);
}
return 0;
- }else if((heapinfo1[block1].type == 0) && (heapinfo2[block2].type == 0)){ /* Complete block */
+ }else if((state->heapinfo1[block1].type == 0) && (state->heapinfo2[block2].type == 0)){ /* Complete block */
- if(equals_to1[block1][0] != NULL && equals_to2[block2][0] != NULL){
- if(equal_blocks(block1, block2)){
+ if(state->equals_to1[block1][0] != NULL && state->equals_to2[block2][0] != NULL){
+ if(equal_blocks(state, block1, block2)){
if(match_pairs){
- match_equals(previous);
+ match_equals(state, previous);
xbt_dynar_free(&previous);
}
return 0;
}
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);
}
if(!add_heap_area_pair(previous, block1, -1, block2, -1)){
if(match_pairs){
- match_equals(previous);
+ match_equals(state, previous);
xbt_dynar_free(&previous);
}
return 0;
}
- size = heapinfo1[block1].busy_block.busy_size;
+ size = state->heapinfo1[block1].busy_block.busy_size;
if(type_id != NULL){
- xbt_free(types1[block1][0]);
- xbt_free(types2[block2][0]);
- types1[block1][0] = strdup(type_id);
- types2[block2][0] = strdup(type_id);
+ xbt_free(state->types1[block1][0]);
+ xbt_free(state->types2[block2][0]);
+ state->types1[block1][0] = strdup(type_id);
+ state->types2[block2][0] = strdup(type_id);
}
if(size <= 0){
if(match_pairs){
- match_equals(previous);
+ match_equals(state, previous);
xbt_dynar_free(&previous);
}
return 0;
area1_to_compare = addr_block1;
area2_to_compare = addr_block2;
- if((heapinfo1[block1].busy_block.ignore > 0) && (heapinfo2[block2].busy_block.ignore == heapinfo1[block1].busy_block.ignore))
- check_ignore = heapinfo1[block1].busy_block.ignore;
+ if((state->heapinfo1[block1].busy_block.ignore > 0) && (state->heapinfo2[block2].busy_block.ignore == state->heapinfo1[block1].busy_block.ignore))
+ check_ignore = state->heapinfo1[block1].busy_block.ignore;
- }else if((heapinfo1[block1].type > 0) && (heapinfo2[block2].type > 0)){ /* Fragmented block */
+ }else if((state->heapinfo1[block1].type > 0) && (state->heapinfo2[block2].type > 0)){ /* Fragmented block */
- frag1 = ((uintptr_t) (ADDR2UINT (area1) % (BLOCKSIZE))) >> heapinfo1[block1].type;
- frag2 = ((uintptr_t) (ADDR2UINT (area2) % (BLOCKSIZE))) >> heapinfo2[block2].type;
+ frag1 = ((uintptr_t) (ADDR2UINT (area1) % (BLOCKSIZE))) >> state->heapinfo1[block1].type;
+ frag2 = ((uintptr_t) (ADDR2UINT (area2) % (BLOCKSIZE))) >> state->heapinfo2[block2].type;
- addr_frag1 = (void*) ((char *)addr_block1 + (frag1 << heapinfo1[block1].type));
- addr_frag2 = (void*) ((char *)addr_block2 + (frag2 << heapinfo2[block2].type));
+ addr_frag1 = (void*) ((char *)addr_block1 + (frag1 << state->heapinfo1[block1].type));
+ addr_frag2 = (void*) ((char *)addr_block2 + (frag2 << state->heapinfo2[block2].type));
- real_addr_frag1 = (void*) ((char *)real_addr_block1 + (frag1 << ((xbt_mheap_t)s_heap)->heapinfo[block1].type));
- real_addr_frag2 = (void*) ((char *)real_addr_block2 + (frag2 << ((xbt_mheap_t)s_heap)->heapinfo[block2].type));
+ real_addr_frag1 = (void*) ((char *)real_addr_block1 + (frag1 << ((xbt_mheap_t)state->s_heap)->heapinfo[block1].type));
+ real_addr_frag2 = (void*) ((char *)real_addr_block2 + (frag2 << ((xbt_mheap_t)state->s_heap)->heapinfo[block2].type));
if(type_size != -1){
- if(heapinfo1[block1].busy_frag.frag_size[frag1] == -1 || heapinfo2[block2].busy_frag.frag_size[frag2] == -1){
+ if(state->heapinfo1[block1].busy_frag.frag_size[frag1] == -1 || state->heapinfo2[block2].busy_frag.frag_size[frag2] == -1){
if(match_pairs){
- match_equals(previous);
+ match_equals(state, previous);
xbt_dynar_free(&previous);
}
return -1;
}
- if(type_size != heapinfo1[block1].busy_frag.frag_size[frag1] || type_size != heapinfo2[block2].busy_frag.frag_size[frag2]){
+ if(type_size != state->heapinfo1[block1].busy_frag.frag_size[frag1]|| type_size != state->heapinfo2[block2].busy_frag.frag_size[frag2]){
if(match_pairs){
- match_equals(previous);
+ match_equals(state, previous);
xbt_dynar_free(&previous);
}
return -1;
}
}
- if(equals_to1[block1][frag1] != NULL && equals_to2[block2][frag2] != NULL){
- if(equal_fragments(block1, frag1, block2, frag2)){
+ if(state->equals_to1[block1][frag1] != NULL && state->equals_to2[block2][frag2] != NULL){
+ if(equal_fragments(state, block1, frag1, block2, frag2)){
if(match_pairs){
- match_equals(previous);
+ match_equals(state, previous);
xbt_dynar_free(&previous);
}
return 0;
}
}
- if(heapinfo1[block1].busy_frag.frag_size[frag1] != heapinfo2[block2].busy_frag.frag_size[frag2]){
+ if(state->heapinfo1[block1].busy_frag.frag_size[frag1] != state->heapinfo2[block2].busy_frag.frag_size[frag2]){
if(type_size == -1){
if(match_pairs){
- match_equals(previous);
+ match_equals(state, previous);
xbt_dynar_free(&previous);
}
return -1;
}
}
- size = heapinfo1[block1].busy_frag.frag_size[frag1];
+ size = state->heapinfo1[block1].busy_frag.frag_size[frag1];
if(type_id != NULL){
- xbt_free(types1[block1][frag1]);
- xbt_free(types2[block2][frag2]);
- types1[block1][frag1] = strdup(type_id);
- types2[block2][frag2] = strdup(type_id);
+ xbt_free(state->types1[block1][frag1]);
+ xbt_free(state->types2[block2][frag2]);
+ state->types1[block1][frag1] = strdup(type_id);
+ state->types2[block2][frag2] = strdup(type_id);
}
if(real_addr_frag1 != area1 || real_addr_frag2 != area2){
offset1 = (char *)area1 - (char *)real_addr_frag1;
offset2 = (char *)area2 - (char *)real_addr_frag2;
- if(types1[block1][frag1] != NULL && types2[block2][frag2] != NULL){
- new_type_id1 = get_offset_type(types1[block1][frag1], offset1, all_types, other_types, size, &switch_type);
- new_type_id2 = get_offset_type(types2[block2][frag2], offset1, all_types, other_types, size, &switch_type);
- }else if(types1[block1][frag1] != NULL){
- new_type_id1 = get_offset_type(types1[block1][frag1], offset1, all_types, other_types, size, &switch_type);
- new_type_id2 = get_offset_type(types1[block1][frag1], offset2, all_types, other_types, size, &switch_type);
- }else if(types2[block2][frag2] != NULL){
- new_type_id1 = get_offset_type(types2[block2][frag2], offset1, all_types, other_types, size, &switch_type);
- new_type_id2 = get_offset_type(types2[block2][frag2], offset2, all_types, other_types, size, &switch_type);
+ if(state->types1[block1][frag1] != NULL && state->types2[block2][frag2] != NULL){
+ new_type_id1 = get_offset_type(state->types1[block1][frag1], offset1, info, other_info, size, &switch_type);
+ new_type_id2 = get_offset_type(state->types2[block2][frag2], offset1, info, other_info, size, &switch_type);
+ }else if(state->types1[block1][frag1] != NULL){
+ new_type_id1 = get_offset_type(state->types1[block1][frag1], offset1, info, other_info, size, &switch_type);
+ new_type_id2 = get_offset_type(state->types1[block1][frag1], offset2, info, other_info, size, &switch_type);
+ }else if(state->types2[block2][frag2] != NULL){
+ new_type_id1 = get_offset_type(state->types2[block2][frag2], offset1, info, other_info, size, &switch_type);
+ new_type_id2 = get_offset_type(state->types2[block2][frag2], offset2, info, other_info, size, &switch_type);
}else{
if(match_pairs){
- match_equals(previous);
+ match_equals(state, previous);
xbt_dynar_free(&previous);
}
return -1;
if(new_type_id1 != NULL && new_type_id2 != NULL && !strcmp(new_type_id1, new_type_id2)){
if(switch_type){
- type = xbt_dict_get_or_null(other_types, new_type_id1);
- while(type->size == 0 && type->dw_type_id != NULL)
- type = xbt_dict_get_or_null(other_types, type->dw_type_id);
- new_size1 = type->size;
- type = xbt_dict_get_or_null(other_types, new_type_id2);
- while(type->size == 0 && type->dw_type_id != NULL)
- type = xbt_dict_get_or_null(other_types, type->dw_type_id);
- new_size2 = type->size;
+ type = xbt_dict_get_or_null(other_info->types, new_type_id1);
+ while(type->byte_size == 0 && type->dw_type_id != NULL)
+ type = xbt_dict_get_or_null(other_info->types, type->dw_type_id);
+ new_size1 = type->byte_size;
+ type = xbt_dict_get_or_null(other_info->types, new_type_id2);
+ while(type->byte_size == 0 && type->dw_type_id != NULL)
+ type = xbt_dict_get_or_null(other_info->types, type->dw_type_id);
+ new_size2 = type->byte_size;
}else{
- type = xbt_dict_get_or_null(all_types, new_type_id1);
- while(type->size == 0 && type->dw_type_id != NULL)
- type = xbt_dict_get_or_null(all_types, type->dw_type_id);
- new_size1 = type->size;
- type = xbt_dict_get_or_null(all_types, new_type_id2);
- while(type->size == 0 && type->dw_type_id != NULL)
- type = xbt_dict_get_or_null(all_types, type->dw_type_id);
- new_size2 = type->size;
+ type = xbt_dict_get_or_null(info->types, new_type_id1);
+ while(type->byte_size == 0 && type->dw_type_id != NULL)
+ type = xbt_dict_get_or_null(info->types, type->dw_type_id);
+ new_size1 = type->byte_size;
+ type = xbt_dict_get_or_null(info->types, new_type_id2);
+ while(type->byte_size == 0 && type->dw_type_id != NULL)
+ type = xbt_dict_get_or_null(info->types, type->dw_type_id);
+ new_size2 = type->byte_size;
}
}else{
if(match_pairs){
- match_equals(previous);
+ match_equals(state, previous);
xbt_dynar_free(&previous);
}
return -1;
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;
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{
/* Start comparison*/
if(type_id != NULL){
if(switch_type)
- res_compare = compare_heap_area_with_type(area1, area2, area1_to_compare, area2_to_compare, previous, other_types, all_types, type_id, size, check_ignore, pointer_level);
+ res_compare = compare_heap_area_with_type(state, area1, area2, area1_to_compare, area2_to_compare, previous, other_info, info, type_id, size, check_ignore, pointer_level);
else
- res_compare = compare_heap_area_with_type(area1, area2, area1_to_compare, area2_to_compare, previous, all_types, other_types, type_id, size, check_ignore, pointer_level);
+ res_compare = compare_heap_area_with_type(state, area1, area2, area1_to_compare, area2_to_compare, previous, info, other_info, type_id, size, check_ignore, pointer_level);
if(res_compare == 1){
if(match_pairs)
xbt_dynar_free(&previous);
}
}else{
if(switch_type)
- res_compare = compare_heap_area_without_type(area1, area2, area1_to_compare, area2_to_compare, previous, other_types, all_types, size, check_ignore);
+ res_compare = compare_heap_area_without_type(state, area1, area2, area1_to_compare, area2_to_compare, previous, other_info, info, size, check_ignore);
else
- res_compare = compare_heap_area_without_type(area1, area2, area1_to_compare, area2_to_compare, previous, all_types, other_types, size, check_ignore);
+ res_compare = compare_heap_area_without_type(state, area1, area2, area1_to_compare, area2_to_compare, previous, info, other_info, size, check_ignore);
if(res_compare == 1){
if(match_pairs)
xbt_dynar_free(&previous);
}
if(match_pairs){
- match_equals(previous);
+ match_equals(state, previous);
xbt_dynar_free(&previous);
}
/*********************************************** 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 */
}
-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;
}
#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;
}
/* Heap information */
- heaplimit = ((struct mdesc *)heap1)->heaplimit;
+ state->heaplimit = ((struct mdesc *)heap1)->heaplimit;
- s_heap = (char *)mmalloc_get_current_heap() - STD_HEAP_SIZE - getpagesize();
+ state->s_heap = (char *)mmalloc_get_current_heap() - STD_HEAP_SIZE - getpagesize();
- heapbase1 = (char *)heap1 + BLOCKSIZE;
- heapbase2 = (char *)heap2 + BLOCKSIZE;
+ state->heapbase1 = (char *)heap1 + BLOCKSIZE;
+ state->heapbase2 = (char *)heap2 + BLOCKSIZE;
- heapinfo1 = (malloc_info *)((char *)heap1 + ((uintptr_t)((char *)heap1->heapinfo - (char *)s_heap)));
- heapinfo2 = (malloc_info *)((char *)heap2 + ((uintptr_t)((char *)heap2->heapinfo - (char *)s_heap)));
+ state->heapinfo1 = (malloc_info *)((char *)heap1 + ((uintptr_t)((char *)heap1->heapinfo - (char *)state->s_heap)));
+ state->heapinfo2 = (malloc_info *)((char *)heap2 + ((uintptr_t)((char *)heap2->heapinfo - (char *)state->s_heap)));
- heapsize1 = heap1->heapsize;
- heapsize2 = heap2->heapsize;
+ state->heapsize1 = heap1->heapsize;
+ state->heapsize2 = heap2->heapsize;
/* Start comparison */
size_t i, j, k;
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;
}
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 ++;
}
}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;
}
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 ++;
}
/* 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;
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);