XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_compare, xbt, "Logging specific to mc_compare in mc");
+using simgrid::mc::remote;
+
namespace simgrid {
namespace mc {
-struct HeapLocation;
-typedef std::array<HeapLocation, 2> HeapLocationPair;
-typedef std::set<HeapLocationPair> HeapLocationPairs;
-struct HeapArea;
-struct ProcessComparisonState;
-struct StateComparator;
-
-static int compare_heap_area(StateComparator& state, const void* area1, const void* area2, Snapshot* snapshot1,
- Snapshot* snapshot2, HeapLocationPairs* previous, Type* type, int pointer_level);
-}
-}
-
-using simgrid::mc::remote;
-
/*********************************** Heap comparison ***********************************/
/***************************************************************************************/
-namespace simgrid {
-namespace mc {
-
class HeapLocation {
public:
int block_ = 0;
}
};
+typedef std::array<HeapLocation, 2> HeapLocationPair;
+typedef std::set<HeapLocationPair> HeapLocationPairs;
+
+struct ProcessComparisonState;
+struct StateComparator;
+
static inline
HeapLocationPair makeHeapLocationPair(int block1, int fragment1, int block2, int fragment2)
{
- return simgrid::mc::HeapLocationPair{{
- simgrid::mc::HeapLocation(block1, fragment1),
- simgrid::mc::HeapLocation(block2, fragment2)
- }};
+ return HeapLocationPair{{HeapLocation(block1, fragment1), HeapLocation(block2, fragment2)}};
}
class HeapArea : public HeapLocation {
void initHeapInformation(xbt_mheap_t heap, std::vector<simgrid::mc::IgnoredHeapRegion>* i);
};
-namespace {
-
-/** A hash which works with more stuff
- *
- * It can hash pairs: the standard hash currently doesn't include this.
- */
-template <class X> class hash : public std::hash<X> {
-};
-
-template <class X, class Y> class hash<std::pair<X, Y>> {
-public:
- std::size_t operator()(std::pair<X,Y>const& x) const
- {
- hash<X> h1;
- hash<X> h2;
- return h1(x.first) ^ h2(x.second);
- }
-};
-
-}
+static int compare_heap_area(StateComparator& state, const void* area1, const void* area2, Snapshot* snapshot1,
+ Snapshot* snapshot2, HeapLocationPairs* previous, Type* type, int pointer_level);
class StateComparator {
public:
std::size_t heaplimit;
std::array<ProcessComparisonState, 2> processStates;
- std::unordered_set<std::pair<void*, void*>, hash<std::pair<void*, void*>>> compared_pointers;
+ std::unordered_set<std::pair<void*, void*>, simgrid::xbt::hash<std::pair<void*, void*>>> compared_pointers;
void clear()
{
xbt_die("No heap region");
}
-static
-int mmalloc_compare_heap(
- simgrid::mc::StateComparator& state, simgrid::mc::Snapshot* snapshot1, simgrid::mc::Snapshot* snapshot2)
+static bool mmalloc_heap_equal(simgrid::mc::StateComparator& state, simgrid::mc::Snapshot* snapshot1,
+ simgrid::mc::Snapshot* snapshot2)
{
simgrid::mc::RemoteClient* process = &mc_model_checker->process();
- /* Start comparison */
- int nb_diff1 = 0;
- int nb_diff2 = 0;
- bool equal;
-
/* Check busy blocks */
size_t i1 = 1;
}
size_t i2 = 1;
- equal = false;
+ bool equal = false;
/* Try first to associate to same block in the other heap */
if (heapinfo2->type == heapinfo1->type && state.equals_to2_(i1, 0).valid_ == 0) {
if (not equal) {
XBT_DEBUG("Block %zu not found (size_used = %zu, addr = %p)", i1, heapinfo1->busy_block.busy_size, addr_block1);
- i1 = state.heaplimit + 1;
- nb_diff1++;
+ return false;
}
} else { /* Fragmented block */
void* addr_frag1 = (void*)((char*)addr_block1 + (j1 << heapinfo1->type));
size_t i2 = 1;
- equal = false;
+ bool equal = false;
/* Try first to associate to same fragment_ in the other heap */
if (heapinfo2->type == heapinfo1->type && not state.equals_to2_(i1, j1).valid_) {
void* addr_frag2 = (void*)((char*)addr_block2 + (j2 << heapinfo2b->type));
int res_compare =
- compare_heap_area(state, addr_frag1, addr_frag2, snapshot2, snapshot2, nullptr, nullptr, 0);
+ compare_heap_area(state, addr_frag1, addr_frag2, snapshot1, snapshot2, nullptr, nullptr, 0);
if (res_compare != 1) {
equal = true;
break;
if (not equal) {
XBT_DEBUG("Block %zu, fragment_ %zu not found (size_used = %zd, address = %p)\n", i1, j1,
heapinfo1->busy_frag.frag_size[j1], addr_frag1);
- i1 = state.heaplimit + 1;
- nb_diff1++;
- break;
+ return false;
}
}
if (heapinfo1->type == MMALLOC_TYPE_UNFRAGMENTED && i1 == state.heaplimit && heapinfo1->busy_block.busy_size > 0 &&
not state.equals_to1_(i, 0).valid_) {
XBT_DEBUG("Block %zu not found (size used = %zu)", i, heapinfo1->busy_block.busy_size);
- nb_diff1++;
+ return false;
}
if (heapinfo1->type <= 0)
for (size_t j = 0; j < (size_t)(BLOCKSIZE >> heapinfo1->type); j++)
if (i1 == state.heaplimit && heapinfo1->busy_frag.frag_size[j] > 0 && not state.equals_to1_(i, j).valid_) {
XBT_DEBUG("Block %zu, Fragment %zu not found (size used = %zd)", i, j, heapinfo1->busy_frag.frag_size[j]);
- nb_diff1++;
+ return false;
}
}
- if (i1 == state.heaplimit)
- XBT_DEBUG("Number of blocks/fragments not found in heap1: %d", nb_diff1);
-
for (size_t i = 1; i < state.heaplimit; i++) {
const malloc_info* heapinfo2 =
(const malloc_info*)heap_region2->read(&heapinfo_temp2, &heapinfos2[i], sizeof(malloc_info));
not state.equals_to2_(i, 0).valid_) {
XBT_DEBUG("Block %zu not found (size used = %zu)", i,
heapinfo2->busy_block.busy_size);
- nb_diff2++;
+ return false;
}
if (heapinfo2->type <= 0)
if (i1 == state.heaplimit && heapinfo2->busy_frag.frag_size[j] > 0 && not state.equals_to2_(i, j).valid_) {
XBT_DEBUG("Block %zu, Fragment %zu not found (size used = %zd)",
i, j, heapinfo2->busy_frag.frag_size[j]);
- nb_diff2++;
+ return false;
}
-
}
- if (i1 == state.heaplimit)
- XBT_DEBUG("Number of blocks/fragments not found in heap2: %d", nb_diff2);
-
- return nb_diff1 > 0 || nb_diff2 > 0;
+ return true;
}
/**
* @param size
* @param check_ignore
*/
-static int compare_heap_area_without_type(simgrid::mc::StateComparator& state, const void* real_area1,
- const void* real_area2, simgrid::mc::Snapshot* snapshot1,
- simgrid::mc::Snapshot* snapshot2, HeapLocationPairs* previous, int size,
- int check_ignore)
+static bool heap_area_equal_without_type(simgrid::mc::StateComparator& state, const void* real_area1,
+ const void* real_area2, simgrid::mc::Snapshot* snapshot1,
+ simgrid::mc::Snapshot* snapshot2, HeapLocationPairs* previous, int size,
+ int check_ignore)
{
simgrid::mc::RemoteClient* process = &mc_model_checker->process();
simgrid::mc::Region* heap_region1 = MC_get_heap_region(snapshot1);
for (int i = 0; i < size; ) {
if (check_ignore > 0) {
- ssize_t ignore1 = heap_comparison_ignore_size(
- state.processStates[0].to_ignore, (char *) real_area1 + i);
+ ssize_t ignore1 = heap_comparison_ignore_size(state.processStates[0].to_ignore, (char*)real_area1 + i);
if (ignore1 != -1) {
- ssize_t ignore2 = heap_comparison_ignore_size(
- state.processStates[1].to_ignore, (char *) real_area2 + i);
+ ssize_t ignore2 = heap_comparison_ignore_size(state.processStates[1].to_ignore, (char*)real_area2 + i);
if (ignore2 == ignore1) {
if (ignore1 == 0) {
check_ignore--;
- return 0;
+ return true;
} else {
i = i + ignore2;
check_ignore--;
&& addr_pointed1 < mc_snapshot_get_heap_end(snapshot1)
&& addr_pointed2 > state.std_heap_copy.heapbase
&& addr_pointed2 < mc_snapshot_get_heap_end(snapshot2)) {
- // Both addreses are in the heap:
+ // Both addresses are in the heap:
int res_compare =
compare_heap_area(state, addr_pointed1, addr_pointed2, snapshot1, snapshot2, previous, nullptr, 0);
if (res_compare == 1)
- return res_compare;
+ return false;
i = pointer_align + sizeof(void *);
continue;
}
- return 1;
+ return false;
}
i++;
}
- return 0;
+ return true;
}
/**
simgrid::mc::Snapshot* snapshot2, HeapLocationPairs* previous,
simgrid::mc::Type* type, int area_size, int check_ignore, int pointer_level)
{
- do {
-
- // HACK: This should not happen but in pratice, there are some
- // DW_TAG_typedef without an associated DW_AT_type:
- //<1><538832>: Abbrev Number: 111 (DW_TAG_typedef)
- // <538833> DW_AT_name : (indirect string, offset: 0x2292f3): gregset_t
- // <538837> DW_AT_decl_file : 98
- // <538838> DW_AT_decl_line : 37
- if (type == nullptr)
- return 0;
-
- if (is_stack(real_area1) && is_stack(real_area2))
- return 0;
+ // HACK: This should not happen but in pratice, there are some
+ // DW_TAG_typedef without an associated DW_AT_type:
+ //<1><538832>: Abbrev Number: 111 (DW_TAG_typedef)
+ // <538833> DW_AT_name : (indirect string, offset: 0x2292f3): gregset_t
+ // <538837> DW_AT_decl_file : 98
+ // <538838> DW_AT_decl_line : 37
+ if (type == nullptr)
+ return 0;
- if (check_ignore > 0) {
- ssize_t ignore1 = heap_comparison_ignore_size(state.processStates[0].to_ignore, real_area1);
- if (ignore1 > 0 && heap_comparison_ignore_size(state.processStates[1].to_ignore, real_area2) == ignore1)
- return 0;
- }
+ if (is_stack(real_area1) && is_stack(real_area2))
+ return 0;
- simgrid::mc::Type* subtype;
- simgrid::mc::Type* subsubtype;
- int elm_size;
- const void* addr_pointed1;
- const void* addr_pointed2;
+ if (check_ignore > 0) {
+ ssize_t ignore1 = heap_comparison_ignore_size(state.processStates[0].to_ignore, real_area1);
+ if (ignore1 > 0 && heap_comparison_ignore_size(state.processStates[1].to_ignore, real_area2) == ignore1)
+ return 0;
+ }
- simgrid::mc::Region* heap_region1 = MC_get_heap_region(snapshot1);
- simgrid::mc::Region* heap_region2 = MC_get_heap_region(snapshot2);
+ simgrid::mc::Type* subtype;
+ simgrid::mc::Type* subsubtype;
+ int elm_size;
+ const void* addr_pointed1;
+ const void* addr_pointed2;
- switch (type->type) {
- case DW_TAG_unspecified_type:
- return 1;
+ simgrid::mc::Region* heap_region1 = MC_get_heap_region(snapshot1);
+ simgrid::mc::Region* heap_region2 = MC_get_heap_region(snapshot2);
- case DW_TAG_base_type:
- if (not type->name.empty() && type->name == "char") { /* String, hence random (arbitrary ?) size */
- if (real_area1 == real_area2)
- return -1;
- else
- return MC_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, area_size) != 0;
- } else {
- if (area_size != -1 && type->byte_size != area_size)
- return -1;
- else
- return MC_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, type->byte_size) != 0;
- }
+ switch (type->type) {
+ case DW_TAG_unspecified_type:
+ return 1;
- case DW_TAG_enumeration_type:
+ case DW_TAG_base_type:
+ if (not type->name.empty() && type->name == "char") { /* String, hence random (arbitrary ?) size */
+ if (real_area1 == real_area2)
+ return -1;
+ else
+ return MC_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, area_size) != 0;
+ } else {
if (area_size != -1 && type->byte_size != area_size)
return -1;
- return MC_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, type->byte_size) != 0;
-
- case DW_TAG_typedef:
- case DW_TAG_const_type:
- case DW_TAG_volatile_type:
- // Poor man's TCO:
- type = type->subtype;
- continue; // restart
-
- case DW_TAG_array_type:
- subtype = type->subtype;
- switch (subtype->type) {
- case DW_TAG_unspecified_type:
- return 1;
-
- case DW_TAG_base_type:
- case DW_TAG_enumeration_type:
- case DW_TAG_pointer_type:
- case DW_TAG_reference_type:
- case DW_TAG_rvalue_reference_type:
- case DW_TAG_structure_type:
- case DW_TAG_class_type:
- case DW_TAG_union_type:
- if (subtype->full_type)
- subtype = subtype->full_type;
- elm_size = subtype->byte_size;
- break;
- // TODO, just remove the type indirection?
- case DW_TAG_const_type:
- case DW_TAG_typedef:
- case DW_TAG_volatile_type:
- subsubtype = subtype->subtype;
- if (subsubtype->full_type)
- subsubtype = subsubtype->full_type;
- elm_size = subsubtype->byte_size;
- break;
- default:
- return 0;
- }
- for (int i = 0; i < type->element_count; i++) {
- // TODO, add support for variable stride (DW_AT_byte_stride)
- int res = compare_heap_area_with_type(state, (char*)real_area1 + (i * elm_size),
- (char*)real_area2 + (i * elm_size), snapshot1, snapshot2, previous,
- type->subtype, subtype->byte_size, check_ignore, pointer_level);
- if (res == 1)
- return res;
- }
- return 0;
+ else
+ return MC_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, type->byte_size) != 0;
+ }
+
+ case DW_TAG_enumeration_type:
+ if (area_size != -1 && type->byte_size != area_size)
+ return -1;
+ return MC_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, type->byte_size) != 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, snapshot1, snapshot2, previous, type->subtype,
+ area_size, check_ignore, pointer_level);
+
+ case DW_TAG_array_type:
+ subtype = type->subtype;
+ switch (subtype->type) {
+ case DW_TAG_unspecified_type:
+ return 1;
- case DW_TAG_reference_type:
- case DW_TAG_rvalue_reference_type:
- case DW_TAG_pointer_type:
- if (type->subtype && type->subtype->type == DW_TAG_subroutine_type) {
- addr_pointed1 = snapshot1->read(remote((void**)real_area1));
- addr_pointed2 = snapshot2->read(remote((void**)real_area2));
+ case DW_TAG_base_type:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_pointer_type:
+ case DW_TAG_reference_type:
+ case DW_TAG_rvalue_reference_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_class_type:
+ case DW_TAG_union_type:
+ if (subtype->full_type)
+ subtype = subtype->full_type;
+ elm_size = subtype->byte_size;
+ break;
+ // TODO, just remove the type indirection?
+ case DW_TAG_const_type:
+ case DW_TAG_typedef:
+ case DW_TAG_volatile_type:
+ subsubtype = subtype->subtype;
+ if (subsubtype->full_type)
+ subsubtype = subsubtype->full_type;
+ elm_size = subsubtype->byte_size;
+ break;
+ default:
+ return 0;
+ }
+ for (int i = 0; i < type->element_count; i++) {
+ // TODO, add support for variable stride (DW_AT_byte_stride)
+ int res = compare_heap_area_with_type(state, (char*)real_area1 + (i * elm_size),
+ (char*)real_area2 + (i * elm_size), snapshot1, snapshot2, previous,
+ type->subtype, subtype->byte_size, check_ignore, pointer_level);
+ if (res == 1)
+ return res;
+ }
+ return 0;
+
+ case DW_TAG_reference_type:
+ case DW_TAG_rvalue_reference_type:
+ case DW_TAG_pointer_type:
+ if (type->subtype && type->subtype->type == DW_TAG_subroutine_type) {
+ addr_pointed1 = snapshot1->read(remote((void**)real_area1));
+ addr_pointed2 = snapshot2->read(remote((void**)real_area2));
+ return (addr_pointed1 != addr_pointed2);
+ }
+ pointer_level++;
+ if (pointer_level <= 1) {
+ addr_pointed1 = snapshot1->read(remote((void**)real_area1));
+ addr_pointed2 = snapshot2->read(remote((void**)real_area2));
+ if (addr_pointed1 > state.std_heap_copy.heapbase && addr_pointed1 < mc_snapshot_get_heap_end(snapshot1) &&
+ addr_pointed2 > state.std_heap_copy.heapbase && addr_pointed2 < mc_snapshot_get_heap_end(snapshot2))
+ return compare_heap_area(state, addr_pointed1, addr_pointed2, snapshot1, snapshot2, previous, type->subtype,
+ pointer_level);
+ else
return (addr_pointed1 != addr_pointed2);
- }
- pointer_level++;
- if (pointer_level <= 1) {
- addr_pointed1 = snapshot1->read(remote((void**)real_area1));
- addr_pointed2 = snapshot2->read(remote((void**)real_area2));
- if (addr_pointed1 > state.std_heap_copy.heapbase && addr_pointed1 < mc_snapshot_get_heap_end(snapshot1) &&
- addr_pointed2 > state.std_heap_copy.heapbase && addr_pointed2 < mc_snapshot_get_heap_end(snapshot2))
- return compare_heap_area(state, addr_pointed1, addr_pointed2, snapshot1, snapshot2, previous, type->subtype,
- pointer_level);
- else
- return (addr_pointed1 != addr_pointed2);
- }
- for (size_t i = 0; i < (area_size / sizeof(void*)); i++) {
- addr_pointed1 = snapshot1->read(remote((void**)((char*)real_area1 + i * sizeof(void*))));
- addr_pointed2 = snapshot2->read(remote((void**)((char*)real_area2 + i * sizeof(void*))));
- int res;
- if (addr_pointed1 > state.std_heap_copy.heapbase && addr_pointed1 < mc_snapshot_get_heap_end(snapshot1) &&
- addr_pointed2 > state.std_heap_copy.heapbase && addr_pointed2 < mc_snapshot_get_heap_end(snapshot2))
- res = compare_heap_area(state, addr_pointed1, addr_pointed2, snapshot1, snapshot2, previous, type->subtype,
- pointer_level);
- else
- res = (addr_pointed1 != addr_pointed2);
+ }
+ for (size_t i = 0; i < (area_size / sizeof(void*)); i++) {
+ addr_pointed1 = snapshot1->read(remote((void**)((char*)real_area1 + i * sizeof(void*))));
+ addr_pointed2 = snapshot2->read(remote((void**)((char*)real_area2 + i * sizeof(void*))));
+ int res;
+ if (addr_pointed1 > state.std_heap_copy.heapbase && addr_pointed1 < mc_snapshot_get_heap_end(snapshot1) &&
+ addr_pointed2 > state.std_heap_copy.heapbase && addr_pointed2 < mc_snapshot_get_heap_end(snapshot2))
+ res = compare_heap_area(state, addr_pointed1, addr_pointed2, snapshot1, snapshot2, previous, type->subtype,
+ pointer_level);
+ else
+ res = (addr_pointed1 != addr_pointed2);
+ if (res == 1)
+ return res;
+ }
+ return 0;
+
+ case DW_TAG_structure_type:
+ case DW_TAG_class_type:
+ if (type->full_type)
+ type = type->full_type;
+ if (area_size != -1 && type->byte_size != area_size) {
+ if (area_size <= type->byte_size || area_size % type->byte_size != 0)
+ return -1;
+ for (size_t i = 0; i < (size_t)(area_size / type->byte_size); i++) {
+ int res = compare_heap_area_with_type(state, (char*)real_area1 + i * type->byte_size,
+ (char*)real_area2 + i * type->byte_size, snapshot1, snapshot2, previous,
+ type, -1, check_ignore, 0);
if (res == 1)
return res;
}
- return 0;
-
- case DW_TAG_structure_type:
- case DW_TAG_class_type:
- if (type->full_type)
- type = type->full_type;
- if (area_size != -1 && type->byte_size != area_size) {
- if (area_size <= type->byte_size || area_size % type->byte_size != 0)
- return -1;
- for (size_t i = 0; i < (size_t)(area_size / type->byte_size); i++) {
- int res = compare_heap_area_with_type(state, (char*)real_area1 + i * type->byte_size,
- (char*)real_area2 + i * type->byte_size, snapshot1, snapshot2,
- previous, type, -1, check_ignore, 0);
- if (res == 1)
- return res;
- }
} else {
for (simgrid::mc::Member& member : type->members) {
// TODO, optimize this? (for the offset case)
}
return 0;
- case DW_TAG_union_type:
- return compare_heap_area_without_type(state, real_area1, real_area2, snapshot1, snapshot2, previous,
+ case DW_TAG_union_type:
+ return not heap_area_equal_without_type(state, real_area1, real_area2, snapshot1, snapshot2, previous,
type->byte_size, check_ignore);
-
- default:
- return 0;
- }
-
- xbt_die("Unreachable");
- } while (true);
+ }
+ return 0;
}
/** Infer the type of a part of the block from the type of the block
check_ignore, pointer_level);
else
res_compare =
- compare_heap_area_without_type(state, area1, area2, snapshot1, snapshot2, previous, size, check_ignore);
+ not heap_area_equal_without_type(state, area1, area2, snapshot1, snapshot2, previous, size, check_ignore);
if (res_compare == 1)
return res_compare;
int i;
int res;
- do {
- xbt_assert(type != nullptr);
- switch (type->type) {
- case DW_TAG_unspecified_type:
- return 1;
+ xbt_assert(type != nullptr);
+ switch (type->type) {
+ case DW_TAG_unspecified_type:
+ return 1;
- case DW_TAG_base_type:
- case DW_TAG_enumeration_type:
- case DW_TAG_union_type:
- return MC_snapshot_region_memcmp(real_area1, region1, real_area2, region2, type->byte_size) != 0;
- case DW_TAG_typedef:
- case DW_TAG_volatile_type:
- case DW_TAG_const_type:
- // Poor man's TCO:
- type = type->subtype;
- continue; // restart
- case DW_TAG_array_type:
- subtype = type->subtype;
- switch (subtype->type) {
- case DW_TAG_unspecified_type:
- return 1;
-
- case DW_TAG_base_type:
- case DW_TAG_enumeration_type:
- case DW_TAG_pointer_type:
- case DW_TAG_reference_type:
- case DW_TAG_rvalue_reference_type:
- case DW_TAG_structure_type:
- case DW_TAG_class_type:
- case DW_TAG_union_type:
- if (subtype->full_type)
- subtype = subtype->full_type;
- elm_size = subtype->byte_size;
- break;
- case DW_TAG_const_type:
- case DW_TAG_typedef:
- case DW_TAG_volatile_type:
- subsubtype = subtype->subtype;
- if (subsubtype->full_type)
- subsubtype = subsubtype->full_type;
- elm_size = subsubtype->byte_size;
- break;
- default:
- return 0;
- }
- for (i = 0; i < type->element_count; i++) {
- size_t off = i * elm_size;
- res = compare_areas_with_type(state, (char*)real_area1 + off, snapshot1, region1, (char*)real_area2 + off,
- snapshot2, region2, type->subtype, pointer_level);
- if (res == 1)
- return res;
- }
- break;
- case DW_TAG_pointer_type:
- case DW_TAG_reference_type:
- case DW_TAG_rvalue_reference_type: {
- void* addr_pointed1 = MC_region_read_pointer(region1, real_area1);
- void* addr_pointed2 = MC_region_read_pointer(region2, real_area2);
-
- if (type->subtype && type->subtype->type == DW_TAG_subroutine_type)
- return (addr_pointed1 != addr_pointed2);
- if (addr_pointed1 == nullptr && addr_pointed2 == nullptr)
- return 0;
- if (addr_pointed1 == nullptr || addr_pointed2 == nullptr)
+ case DW_TAG_base_type:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_union_type:
+ return MC_snapshot_region_memcmp(real_area1, region1, real_area2, region2, type->byte_size) != 0;
+ case DW_TAG_typedef:
+ case DW_TAG_volatile_type:
+ case DW_TAG_const_type:
+ return compare_areas_with_type(state, real_area1, snapshot1, region1, real_area2, snapshot2, region2,
+ type->subtype, pointer_level);
+ case DW_TAG_array_type:
+ subtype = type->subtype;
+ switch (subtype->type) {
+ case DW_TAG_unspecified_type:
return 1;
- if (not state.compared_pointers.insert(std::make_pair(addr_pointed1, addr_pointed2)).second)
+
+ case DW_TAG_base_type:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_pointer_type:
+ case DW_TAG_reference_type:
+ case DW_TAG_rvalue_reference_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_class_type:
+ case DW_TAG_union_type:
+ if (subtype->full_type)
+ subtype = subtype->full_type;
+ elm_size = subtype->byte_size;
+ break;
+ case DW_TAG_const_type:
+ case DW_TAG_typedef:
+ case DW_TAG_volatile_type:
+ subsubtype = subtype->subtype;
+ if (subsubtype->full_type)
+ subsubtype = subsubtype->full_type;
+ elm_size = subsubtype->byte_size;
+ break;
+ default:
return 0;
+ }
+ for (i = 0; i < type->element_count; i++) {
+ size_t off = i * elm_size;
+ res = compare_areas_with_type(state, (char*)real_area1 + off, snapshot1, region1, (char*)real_area2 + off,
+ snapshot2, region2, type->subtype, pointer_level);
+ if (res == 1)
+ return res;
+ }
+ break;
+ case DW_TAG_pointer_type:
+ case DW_TAG_reference_type:
+ case DW_TAG_rvalue_reference_type: {
+ void* addr_pointed1 = MC_region_read_pointer(region1, real_area1);
+ void* addr_pointed2 = MC_region_read_pointer(region2, real_area2);
+
+ if (type->subtype && type->subtype->type == DW_TAG_subroutine_type)
+ return (addr_pointed1 != addr_pointed2);
+ if (addr_pointed1 == nullptr && addr_pointed2 == nullptr)
+ return 0;
+ if (addr_pointed1 == nullptr || addr_pointed2 == nullptr)
+ return 1;
+ if (not state.compared_pointers.insert(std::make_pair(addr_pointed1, addr_pointed2)).second)
+ return 0;
- pointer_level++;
-
- // Some cases are not handled here:
- // * the pointers lead to different areas (one to the heap, the other to the RW segment ...)
- // * a pointer leads to the read-only segment of the current object
- // * a pointer lead to a different ELF object
-
- if (addr_pointed1 > process->heap_address && addr_pointed1 < mc_snapshot_get_heap_end(snapshot1)) {
- if (not(addr_pointed2 > process->heap_address && addr_pointed2 < mc_snapshot_get_heap_end(snapshot2)))
- return 1;
- // The pointers are both in the heap:
- return simgrid::mc::compare_heap_area(state, addr_pointed1, addr_pointed2, snapshot1, snapshot2, nullptr,
- type->subtype, pointer_level);
-
- } else if (region1->contain(simgrid::mc::remote(addr_pointed1))) {
- // The pointers are both in the current object R/W segment:
- if (not region2->contain(simgrid::mc::remote(addr_pointed2)))
- return 1;
- if (not type->type_id)
- return (addr_pointed1 != addr_pointed2);
- else
- return compare_areas_with_type(state, addr_pointed1, snapshot1, region1, addr_pointed2, snapshot2, region2,
- type->subtype, pointer_level);
- } else {
+ pointer_level++;
- // TODO, We do not handle very well the case where
- // it belongs to a different (non-heap) region from the current one.
+ // 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
+ if (addr_pointed1 > process->heap_address && addr_pointed1 < mc_snapshot_get_heap_end(snapshot1)) {
+ if (not(addr_pointed2 > process->heap_address && addr_pointed2 < mc_snapshot_get_heap_end(snapshot2)))
+ return 1;
+ // The pointers are both in the heap:
+ return simgrid::mc::compare_heap_area(state, addr_pointed1, addr_pointed2, snapshot1, snapshot2, nullptr,
+ type->subtype, pointer_level);
+
+ } else if (region1->contain(simgrid::mc::remote(addr_pointed1))) {
+ // The pointers are both in the current object R/W segment:
+ if (not region2->contain(simgrid::mc::remote(addr_pointed2)))
+ return 1;
+ if (not type->type_id)
return (addr_pointed1 != addr_pointed2);
- }
+ else
+ return compare_areas_with_type(state, addr_pointed1, snapshot1, region1, addr_pointed2, snapshot2, region2,
+ type->subtype, pointer_level);
+ } else {
+
+ // TODO, We do not handle very well the case where
+ // it belongs to a different (non-heap) region from the current one.
+
+ return (addr_pointed1 != addr_pointed2);
}
- case DW_TAG_structure_type:
- case DW_TAG_class_type:
- for (simgrid::mc::Member& member : type->members) {
- void* member1 = simgrid::dwarf::resolve_member(real_area1, type, &member, snapshot1);
- void* member2 = simgrid::dwarf::resolve_member(real_area2, type, &member, snapshot2);
- simgrid::mc::Region* subregion1 = snapshot1->get_region(member1, region1); // region1 is hinted
- simgrid::mc::Region* subregion2 = snapshot2->get_region(member2, region2); // region2 is hinted
- res = compare_areas_with_type(state, member1, snapshot1, subregion1, member2, snapshot2, subregion2,
- member.type, pointer_level);
- if (res == 1)
- return res;
- }
- break;
- case DW_TAG_subroutine_type:
- return -1;
- default:
- XBT_VERB("Unknown case: %d", type->type);
- break;
}
+ case DW_TAG_structure_type:
+ case DW_TAG_class_type:
+ for (simgrid::mc::Member& member : type->members) {
+ void* member1 = simgrid::dwarf::resolve_member(real_area1, type, &member, snapshot1);
+ void* member2 = simgrid::dwarf::resolve_member(real_area2, type, &member, snapshot2);
+ simgrid::mc::Region* subregion1 = snapshot1->get_region(member1, region1); // region1 is hinted
+ simgrid::mc::Region* subregion2 = snapshot2->get_region(member2, region2); // region2 is hinted
+ res = compare_areas_with_type(state, member1, snapshot1, subregion1, member2, snapshot2, subregion2,
+ member.type, pointer_level);
+ if (res == 1)
+ return res;
+ }
+ break;
+ case DW_TAG_subroutine_type:
+ return -1;
+ default:
+ XBT_VERB("Unknown case: %d", type->type);
+ break;
+ }
- return 0;
- } while (true);
+ return 0;
}
static bool global_variables_equal(simgrid::mc::StateComparator& state, simgrid::mc::ObjectInformation* object_info,
current_var2->subprogram->name.c_str(), current_var1->ip, current_var2->ip);
return false;
}
- // TODO, fix current_varX->subprogram->name to include name if DW_TAG_inlined_subprogram
if (compare_areas_with_type(state, current_var1->address, snapshot1, snapshot1->get_region(current_var1->address),
current_var2->address, snapshot2, snapshot2->get_region(current_var2->address),
current_var1->type, 0) == 1) {
- // TODO, fix current_varX->subprogram->name to include name if DW_TAG_inlined_subprogram
XBT_VERB("Local variable %s (%p - %p) in frame %s "
"is different between snapshots",
current_var1->name.c_str(), current_var1->address, current_var2->address,
}
/* Compare heap */
- if (mmalloc_compare_heap(*state_comparator, s1, s2) > 0) {
+ if (not mmalloc_heap_equal(*state_comparator, s1, s2)) {
XBT_VERB("(%d - %d) Different heap (mmalloc_compare)", s1->num_state_, s2->num_state_);
return false;
}