From 1ba8e265192b67c6903d48faeabe9e1d626bcd3d Mon Sep 17 00:00:00 2001 From: Gabriel Corona Date: Mon, 10 Mar 2014 14:11:30 +0100 Subject: [PATCH] [mc] Add location field in struct/class-members Store location expression for fields when its location expression is more complex than a simple offset. --- buildtools/Cmake/DefinePackages.cmake | 3 +- src/include/mc/datatypes.h | 14 -- src/mc/mc_checkpoint.c | 16 +++ src/mc/mc_compare.c | 4 +- src/mc/mc_dwarf.c | 2 +- src/mc/mc_dwarf_expression.c | 2 - src/mc/mc_global.c | 1 + src/mc/mc_hash.c | 3 +- src/mc/mc_member.c | 51 ++++++++ src/mc/mc_private.h | 25 ++++ src/xbt/mmalloc/mm_diff.c | 176 +++++++++++++++++++++++--- 11 files changed, 257 insertions(+), 40 deletions(-) create mode 100644 src/mc/mc_member.c diff --git a/buildtools/Cmake/DefinePackages.cmake b/buildtools/Cmake/DefinePackages.cmake index eacfccbf29..0f610f77d8 100644 --- a/buildtools/Cmake/DefinePackages.cmake +++ b/buildtools/Cmake/DefinePackages.cmake @@ -542,7 +542,8 @@ set(MC_SRC src/mc/mc_compare.c src/mc/mc_dpor.c src/mc/mc_global.c - src/mc/mc_dwarf.c + src/mc/mc_dwarf + src/mc/mc_member.c src/mc/mc_dwarf_expression.c src/mc/mc_liveness.c src/mc/mc_memory.c diff --git a/src/include/mc/datatypes.h b/src/include/mc/datatypes.h index 2c4f48d47f..cd8caab749 100644 --- a/src/include/mc/datatypes.h +++ b/src/include/mc/datatypes.h @@ -53,20 +53,6 @@ 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; /* 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_class_type, DW_TAG_union_type*/ - int is_pointer_type; - int offset; - 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(mc_object_info_t info, char *type_name); SG_END_DECL() diff --git a/src/mc/mc_checkpoint.c b/src/mc/mc_checkpoint.c index 49e12af20b..e72bef316a 100644 --- a/src/mc/mc_checkpoint.c +++ b/src/mc/mc_checkpoint.c @@ -475,6 +475,22 @@ void* mc_translate_address(uintptr_t addr, mc_snapshot_t snapshot) { return (void*) addr; } +uintptr_t mc_untranslate_address(void* addr, mc_snapshot_t snapshot) { + if(!snapshot) { + return (uintptr_t) addr; + } + + for(size_t i=0; i!=NB_REGIONS; ++i) { + mc_mem_region_t region = snapshot->regions[i]; + if(addr>=region->data && addr<=region->data+region->size) { + size_t offset = (size_t) ((char*) addr - (char*) region->data); + return (uintptr_t) (region->start_addr + offset); + } + } + + return (uintptr_t) addr; +} + mc_snapshot_t SIMIX_pre_mc_snapshot(smx_simcall_t simcall){ return MC_take_snapshot(1); } diff --git a/src/mc/mc_compare.c b/src/mc/mc_compare.c index a728239044..4bb3b2d1af 100644 --- a/src/mc/mc_compare.c +++ b/src/mc/mc_compare.c @@ -212,7 +212,9 @@ static int compare_areas_with_type(void *area1, void *area2, mc_snapshot_t snaps case DW_TAG_class_type: xbt_dynar_foreach(type->members, cursor, member){ XBT_DEBUG("Compare member %s", member->name); - res = compare_areas_with_type((char *)area1 + member->offset, (char *)area2 + member->offset, snapshot1, snapshot2, info, other_info, member->subtype, region_size, region_type, start_data, pointer_level); + void* member1 = mc_member_snapshot_resolve(area1, type, member, snapshot1); + void* member2 = mc_member_snapshot_resolve(area2, type, member, snapshot2); + res = compare_areas_with_type(member1, member2, snapshot1, snapshot2, info, other_info, member->subtype, region_size, region_type, start_data, pointer_level); if(res == 1) return res; } diff --git a/src/mc/mc_dwarf.c b/src/mc/mc_dwarf.c index 4db8355de7..80b9bddf18 100644 --- a/src/mc/mc_dwarf.c +++ b/src/mc/mc_dwarf.c @@ -416,7 +416,7 @@ static void MC_dwarf_fill_member_location(dw_type_t type, dw_type_t member, Dwar 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."); + mc_dwarf_expression_init(&member->location, len, expr); } break; } diff --git a/src/mc/mc_dwarf_expression.c b/src/mc/mc_dwarf_expression.c index b45645ec20..0bc9dcca06 100644 --- a/src/mc/mc_dwarf_expression.c +++ b/src/mc/mc_dwarf_expression.c @@ -299,7 +299,6 @@ void* mc_find_frame_base(dw_frame_t frame, unw_cursor_t* unw_cursor) { return (void*) mc_dwarf_resolve_locations(&frame->frame_base, unw_cursor, NULL, NULL); } -static void mc_dwarf_expression_clear(mc_expression_t expression) { free(expression->ops); expression->ops = NULL; @@ -317,7 +316,6 @@ void mc_dwarf_location_list_clear(mc_location_list_t list) { list->size = 0; } -static void mc_dwarf_expression_init(mc_expression_t expression, size_t len, Dwarf_Op* ops) { if(expression->ops) { free(expression->ops); diff --git a/src/mc/mc_global.c b/src/mc/mc_global.c index 21176a0479..f5d183b3f9 100644 --- a/src/mc/mc_global.c +++ b/src/mc/mc_global.c @@ -156,6 +156,7 @@ void dw_type_free(dw_type_t t){ xbt_free(t->name); xbt_free(t->dw_type_id); xbt_dynar_free(&(t->members)); + mc_dwarf_expression_clear(&t->location); xbt_free(t); } diff --git a/src/mc/mc_hash.c b/src/mc/mc_hash.c index 2916ed28ee..5b824aeb12 100644 --- a/src/mc/mc_hash.c +++ b/src/mc/mc_hash.c @@ -137,7 +137,8 @@ static void mc_hash_value(mc_hash_t* hash, mc_hashing_state* state, mc_object_in 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); + void* member_variable = mc_member_resolve(address, type, member, NULL); + mc_hash_value(hash, state, info, member_variable, type->subtype); } return; } diff --git a/src/mc/mc_member.c b/src/mc/mc_member.c new file mode 100644 index 0000000000..d89456718a --- /dev/null +++ b/src/mc/mc_member.c @@ -0,0 +1,51 @@ +#include "mc_private.h" + +/** Resolve snapshot in the process address space + * + * @param object Process address of the struct/class + * @param type Type of the struct/class + * @param member Member description + * @param snapshot Snapshot (or NULL) + * @return Process address of the given member of the 'object' struct/class + */ +void* mc_member_resolve(const void* base, dw_type_t type, dw_type_t member, mc_snapshot_t snapshot) { + if(!member->location.size) { + return ((char*) base) + member->offset; + } + + s_mc_expression_state_t state; + memset(&state, 0, sizeof(s_mc_expression_state_t)); + state.frame_base = NULL; + state.cursor = NULL; + state.snapshot = snapshot; + state.stack_size = 1; + state.stack[0] = (uintptr_t) base; + + if(mc_dwarf_execute_expression(member->location.size, member->location.ops, &state)) + xbt_die("Error evaluating DWARF expression"); + if(state.stack_size==0) + xbt_die("No value on the stack"); + else + return (void*) state.stack[state.stack_size-1]; +} + +/** Resolve snapshot in the snapshot address space + * + * @param object Snapshot address of the struct/class + * @param type Type of the struct/class + * @param member Member description + * @param snapshot Snapshot (or NULL) + * @return Snapshot address of the given member of the 'object' struct/class + */ +void* mc_member_snapshot_resolve(const void* object, dw_type_t type, dw_type_t member, mc_snapshot_t snapshot) { + if(!member->location.size) { + return (char*) object + member->offset; + } else { + // Translate the problem in the process address space: + void* real_area = (void*) mc_untranslate_address((void *)object, snapshot); + // Resolve the member in the process address space: + void* real_member = mc_member_resolve(real_area, type, member, snapshot); + // Translate back in the snapshot address space: + return mc_translate_address((uintptr_t)real_member, snapshot); + } +} diff --git a/src/mc/mc_private.h b/src/mc/mc_private.h index ae9bad14fa..fa2945f8eb 100644 --- a/src/mc/mc_private.h +++ b/src/mc/mc_private.h @@ -95,6 +95,7 @@ mc_snapshot_t MC_take_snapshot(int num_state); void MC_restore_snapshot(mc_snapshot_t); void MC_free_snapshot(mc_snapshot_t); void* mc_translate_address(uintptr_t addr, mc_snapshot_t snapshot); +uintptr_t mc_untranslate_address(void* addr, mc_snapshot_t snapshot); extern xbt_dynar_t mc_checkpoint_ignore; @@ -393,6 +394,9 @@ typedef struct s_mc_location_list { Dwarf_Off mc_dwarf_resolve_location(mc_expression_t expression, unw_cursor_t* c, void* frame_pointer_address, mc_snapshot_t snapshot); Dwarf_Off mc_dwarf_resolve_locations(mc_location_list_t locations, unw_cursor_t* c, void* frame_pointer_address, mc_snapshot_t snapshot); +void mc_dwarf_expression_clear(mc_expression_t expression); +void mc_dwarf_expression_init(mc_expression_t expression, size_t len, Dwarf_Op* ops); + void mc_dwarf_location_list_clear(mc_location_list_t list); void mc_dwarf_location_list_init_from_expression(mc_location_list_t target, size_t len, Dwarf_Op* ops); @@ -400,6 +404,27 @@ void mc_dwarf_location_list_init(mc_location_list_t target, mc_object_info_t inf // ***** Variables and functions +struct s_dw_type{ + e_dw_type_type type; + void *id; /* Offset in the section (in hexadecimal form) */ + char *name; /* Name of the type */ + int byte_size; /* Size in bytes */ + int element_count; /* Number of elements for array type */ + char *dw_type_id; /* DW_AT_type id */ + xbt_dynar_t members; /* if DW_TAG_structure_type, DW_TAG_class_type, DW_TAG_union_type*/ + int is_pointer_type; + + // Location (for members) is either of: + struct s_mc_expression location; + int offset; + + dw_type_t subtype; // DW_AT_type + dw_type_t other_object_same_type; // The same (but more complete) type in the other object. +}; + +void* mc_member_resolve(const void* base, dw_type_t type, dw_type_t member, mc_snapshot_t snapshot); +void* mc_member_snapshot_resolve(const void* base, dw_type_t type, dw_type_t member, mc_snapshot_t snapshot); + typedef struct s_dw_variable{ Dwarf_Off dwarf_offset; /* Global offset of the field. */ int global; diff --git a/src/xbt/mmalloc/mm_diff.c b/src/xbt/mmalloc/mm_diff.c index cc06d0395f..a634e67550 100644 --- a/src/xbt/mmalloc/mm_diff.c +++ b/src/xbt/mmalloc/mm_diff.c @@ -136,7 +136,9 @@ typedef char* type_name; struct s_mm_diff { void *s_heap, *heapbase1, *heapbase2; malloc_info *heapinfo1, *heapinfo2; - size_t heaplimit, heapsize1, heapsize2; + size_t heaplimit; + // Number of blocks in the heaps: + size_t heapsize1, heapsize2; xbt_dynar_t to_ignore1, to_ignore2; heap_area_t **equals_to1, **equals_to2; type_name **types1, **types2; @@ -296,6 +298,13 @@ static void match_equals(struct s_mm_diff *state, xbt_dynar_t list){ } } +/** Check whether two blocks are known to be matching + * + * @param state State used + * @param b1 Block of state 1 + * @param b2 Block of state 2 + * @return if the blocks are known to be matching + */ static int equal_blocks(struct s_mm_diff *state, int b1, int b2){ if(state->equals_to1[b1][0]->block == b2 && state->equals_to2[b2][0]->block == b1) @@ -304,6 +313,15 @@ static int equal_blocks(struct s_mm_diff *state, int b1, int b2){ return 0; } +/** Check whether two fragments are known to be matching + * + * @param state State used + * @param b1 Block of state 1 + * @param f1 Fragment of state 1 + * @param b2 Block of state 2 + * @param f2 Fragment of state 2 + * @return if the fragments are known to be matching + */ static int equal_fragments(struct s_mm_diff *state, int b1, int f1, int b2, int f2){ if(state->equals_to1[b1][f1]->block == b2 @@ -704,6 +722,21 @@ int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2, xbt_m return ((nb_diff1 > 0) || (nb_diff2 > 0)); } +/** + * + * @param state + * @param real_area1 Process address for state 1 + * @param real_area2 Process address for state 2 + * @param area1 Snapshot address for state 1 + * @param area2 Snapshot address for state 2 + * @param snapshot1 Snapshot of state 1 + * @param snapshot2 Snapshot of state 2 + * @param previous + * @param info + * @param other_info + * @param size + * @param check_ignore + */ static int compare_heap_area_without_type(struct s_mm_diff *state, void *real_area1, void *real_area2, void *area1, void *area2, mc_snapshot_t snapshot1, mc_snapshot_t snapshot2, xbt_dynar_t previous, mc_object_info_t info, mc_object_info_t other_info, int size, int check_ignore){ int i = 0; @@ -759,7 +792,24 @@ static int compare_heap_area_without_type(struct s_mm_diff *state, void *real_ar } -// area_size is either a byte_size or an elements_count?& +/** + * + * @param state + * @param real_area1 Process address for state 1 + * @param real_area2 Process address for state 2 + * @param area1 Snapshot address for state 1 + * @param area2 Snapshot address for state 2 + * @param snapshot1 Snapshot of state 1 + * @param snapshot2 Snapshot of state 2 + * @param previous + * @param info + * @param other_info + * @param type_id + * @param area_size either a byte_size or an elements_count (?) + * @param check_ignore + * @param pointer_level + * @return 0 (same), 1 (different), -1 (unknown) + */ static int compare_heap_area_with_type(struct s_mm_diff *state, void *real_area1, void *real_area2, void *area1, void *area2, mc_snapshot_t snapshot1, mc_snapshot_t snapshot2, xbt_dynar_t previous, mc_object_info_t info, mc_object_info_t other_info, char *type_id, @@ -911,11 +961,16 @@ static int compare_heap_area_with_type(struct s_mm_diff *state, void *real_area1 } }else{ cursor = 0; - xbt_dynar_foreach(type->members, cursor, member){ + xbt_dynar_foreach(type->members, cursor, member){ + // TODO, optimize this? (for the offset case) + char* real_member1 = mc_member_resolve(real_area1, type, member, snapshot1); + char* real_member2 = mc_member_resolve(real_area2, type, member, snapshot2); + char* member1 = mc_translate_address((uintptr_t)real_member1, snapshot1); + char* member2 = mc_translate_address((uintptr_t)real_member2, snapshot2); if(switch_types) - 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, snapshot1, snapshot2, previous, other_info, info, member->dw_type_id, -1, check_ignore, 0); + res = compare_heap_area_with_type(state, real_member1, real_member2, member1, member2, snapshot1, snapshot2, previous, other_info, info, member->dw_type_id, -1, check_ignore, 0); else - 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, snapshot1, snapshot2, previous, info, other_info, member->dw_type_id, -1, check_ignore, 0); + res = compare_heap_area_with_type(state, real_member1, real_member2, member1, member2, snapshot1, snapshot2, previous, info, other_info, member->dw_type_id, -1, check_ignore, 0); if(res == 1){ return res; } @@ -933,12 +988,31 @@ static int compare_heap_area_with_type(struct s_mm_diff *state, void *real_area1 } -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){ +/** Infer the type of a part of the block from the type of the block + * + * TODO, handle DW_TAG_array_type as well as arrays of the object ((*p)[5], p[5]) + * + * TODO, handle subfields ((*p).bar.foo, (*p)[5].bar…) + * + * @param type_id DWARF type ID of the root address (in info) + * @param info object debug information of the type of ther root address + * @param other_info other debug information + * @param area_size + * @param switch_type (out) whether the resulting type is in info (false) or in other_info (true) + * @return DWARF type ID in either info or other_info + */ +static char* get_offset_type(void* real_base_address, char* type_id, int offset, mc_object_info_t info, mc_object_info_t other_info, int area_size, mc_snapshot_t snapshot, int *switch_type){ + + // Beginning of the block, the infered variable type if the type of the block: + if(offset==0) + return type_id; + dw_type_t type = xbt_dict_get_or_null(info->types, type_id); if(type == NULL){ type = xbt_dict_get_or_null(other_info->types, type_id); *switch_type = 1; } + switch(type->type){ case DW_TAG_structure_type : case DW_TAG_class_type: @@ -971,8 +1045,17 @@ static char* get_offset_type(char* type_id, int offset, mc_object_info_t info, m unsigned int cursor = 0; dw_type_t member; xbt_dynar_foreach(type->members, cursor, member){ - if(member->offset == offset) - return member->dw_type_id; + + if(!member->location.size) { + // We have the offset, use it directly (shortcut): + if(member->offset == offset) + return member->dw_type_id; + } else { + char* real_member = mc_member_resolve(real_base_address, type, member, snapshot); + if(real_member - (char*)real_base_address == offset) + return member->dw_type_id; + } + } return NULL; } @@ -984,6 +1067,19 @@ static char* get_offset_type(char* type_id, int offset, mc_object_info_t info, m } } +/** + * + * @param area1 Process address for state 1 + * @param area2 Process address for state 2 + * @param snapshot1 Snapshot of state 1 + * @param snapshot2 Snapshot of state 2 + * @param previous Pairs of blocks already compared on the current path (or NULL) + * @param info + * @param other_info + * @param type_id Type of variable + * @param pointer_level + * @return 0 (same), 1 (different), -1 + */ int compare_heap_area(void *area1, void* area2, mc_snapshot_t snapshot1, mc_snapshot_t snapshot2, xbt_dynar_t previous, 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; @@ -1009,9 +1105,11 @@ int compare_heap_area(void *area1, void* area2, mc_snapshot_t snapshot1, mc_snap match_pairs = 1; } + // Get block number: block1 = ((char*)area1 - (char*)((xbt_mheap_t)state->s_heap)->heapbase) / BLOCKSIZE + 1; block2 = ((char*)area2 - (char*)((xbt_mheap_t)state->s_heap)->heapbase) / BLOCKSIZE + 1; + // If either block is a stack block: if(is_block_stack((int)block1) && is_block_stack((int)block2)){ add_heap_area_pair(previous, block1, -1, block2, -1); if(match_pairs){ @@ -1021,20 +1119,26 @@ int compare_heap_area(void *area1, void* area2, mc_snapshot_t snapshot1, mc_snap return 0; } - 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 either block is not in the expected area of memory: + if(((char *)area1 < (char*)((xbt_mheap_t)state->s_heap)->heapbase) || (block1 > state->heapsize1) || (block1 < 1) + || ((char *)area2 < (char*)((xbt_mheap_t)state->s_heap)->heapbase) || (block2 > state->heapsize2) || (block2 < 1)){ if(match_pairs){ xbt_dynar_free(&previous); } return 1; } + // Snapshot address of the block: addr_block1 = ((void*) (((ADDR2UINT(block1)) - 1) * BLOCKSIZE + (char*)state->heapbase1)); addr_block2 = ((void*) (((ADDR2UINT(block2)) - 1) * BLOCKSIZE + (char*)state->heapbase2)); + // Process address of the block: real_addr_block1 = ((void*) (((ADDR2UINT(block1)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)state->s_heap)->heapbase)); real_addr_block2 = ((void*) (((ADDR2UINT(block2)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)state->s_heap)->heapbase)); if(type_id){ + + // Lookup type: type = xbt_dict_get_or_null(info->types, type_id); if(type->byte_size == 0){ if(type->subtype == NULL){ @@ -1047,10 +1151,13 @@ int compare_heap_area(void *area1, void* area2, mc_snapshot_t snapshot1, mc_snap type = type->subtype; } } + + // Find type_size: if((type->type == DW_TAG_pointer_type) || ((type->type == DW_TAG_base_type) && type->name!=NULL && (!strcmp(type->name, "char")))) type_size = -1; else type_size = type->byte_size; + } if((state->heapinfo1[block1].type == -1) && (state->heapinfo2[block2].type == -1)){ /* Free block */ @@ -1063,6 +1170,8 @@ int compare_heap_area(void *area1, void* area2, mc_snapshot_t snapshot1, mc_snap }else if((state->heapinfo1[block1].type == 0) && (state->heapinfo2[block2].type == 0)){ /* Complete block */ + // TODO, lookup variable type from block type as done for fragmented blocks + if(state->equals_to1[block1][0] != NULL && state->equals_to2[block2][0] != NULL){ if(equal_blocks(state, block1, block2)){ if(match_pairs){ @@ -1109,10 +1218,14 @@ int compare_heap_area(void *area1, void* area2, mc_snapshot_t snapshot1, mc_snap size = state->heapinfo1[block1].busy_block.busy_size; - if(type_id != NULL){ + // Remember (basic) type inference. + // The current data structure only allows us to do this for the whole block. + if (type_id != NULL && area1==real_addr_block1) { xbt_free(state->types1[block1][0]); - xbt_free(state->types2[block2][0]); state->types1[block1][0] = strdup(type_id); + } + if (type_id != NULL && area2==real_addr_block2) { + xbt_free(state->types2[block2][0]); state->types2[block2][0] = strdup(type_id); } @@ -1135,15 +1248,19 @@ int compare_heap_area(void *area1, void* area2, mc_snapshot_t snapshot1, mc_snap }else if((state->heapinfo1[block1].type > 0) && (state->heapinfo2[block2].type > 0)){ /* Fragmented block */ + // Fragment number: frag1 = ((uintptr_t) (ADDR2UINT (area1) % (BLOCKSIZE))) >> state->heapinfo1[block1].type; frag2 = ((uintptr_t) (ADDR2UINT (area2) % (BLOCKSIZE))) >> state->heapinfo2[block2].type; + // Snapshot address of the fragment: addr_frag1 = (void*) ((char *)addr_block1 + (frag1 << state->heapinfo1[block1].type)); addr_frag2 = (void*) ((char *)addr_block2 + (frag2 << state->heapinfo2[block2].type)); + // Process address of the fragment: real_addr_frag1 = (void*) ((char *)real_addr_block1 + (frag1 << ((xbt_mheap_t)state->s_heap)->heapinfo[block1].type)); real_addr_frag2 = (void*) ((char *)real_addr_block2 + (frag2 << ((xbt_mheap_t)state->s_heap)->heapinfo[block2].type)); + // Check the size of the fragments against the size of the type: if(type_size != -1){ if(state->heapinfo1[block1].busy_frag.frag_size[frag1] == -1 || state->heapinfo2[block2].busy_frag.frag_size[frag2] == -1){ if(match_pairs){ @@ -1161,6 +1278,7 @@ int compare_heap_area(void *area1, void* area2, mc_snapshot_t snapshot1, mc_snap } } + // Check if the blocks are already matched together: if(state->equals_to1[block1][frag1] != NULL && state->equals_to2[block2][frag2] != NULL){ if(equal_fragments(state, block1, frag1, block2, frag2)){ if(match_pairs){ @@ -1171,6 +1289,7 @@ int compare_heap_area(void *area1, void* area2, mc_snapshot_t snapshot1, mc_snap } } + // Compare the size of both fragments: if(state->heapinfo1[block1].busy_frag.frag_size[frag1] != state->heapinfo2[block2].busy_frag.frag_size[frag2]){ if(type_size == -1){ if(match_pairs){ @@ -1186,27 +1305,44 @@ int compare_heap_area(void *area1, void* area2, mc_snapshot_t snapshot1, mc_snap } } + // Size of the fragment: size = state->heapinfo1[block1].busy_frag.frag_size[frag1]; - if(type_id != NULL){ + // Remember (basic) type inference. + // The current data structure only allows us to do this for the whole block. + if(type_id != NULL && area1==real_addr_frag1){ xbt_free(state->types1[block1][frag1]); - xbt_free(state->types2[block2][frag2]); state->types1[block1][frag1] = strdup(type_id); + } + if(type_id != NULL && area2==real_addr_frag2) { + xbt_free(state->types2[block2][frag2]); state->types2[block2][frag2] = strdup(type_id); } - if(real_addr_frag1 != area1 || real_addr_frag2 != area2){ + // The type of the variable is already known: + if(type_id) { + new_type_id1 = type_id; + new_type_id2 = type_id; + } + + // Type inference from the block type. + // Correctness bug: we do not know from which object the type comes. + // This code is disabled for this reason. + // TODO, fix by using the type instead of the type global DWARF offset. + else if(0 && (state->types1[block1][frag1] != NULL || state->types2[block2][frag2] != NULL)) { + offset1 = (char *)area1 - (char *)real_addr_frag1; offset2 = (char *)area2 - (char *)real_addr_frag2; + 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); + new_type_id1 = get_offset_type(real_addr_frag1, state->types1[block1][frag1], offset1, info, other_info, size, snapshot1, &switch_type); + new_type_id2 = get_offset_type(real_addr_frag2, state->types2[block2][frag2], offset1, info, other_info, size, snapshot2, &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); + new_type_id1 = get_offset_type(real_addr_frag1, state->types1[block1][frag1], offset1, info, other_info, size, snapshot1, &switch_type); + new_type_id2 = get_offset_type(real_addr_frag2, state->types1[block1][frag1], offset2, info, other_info, size, snapshot2, &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); + new_type_id1 = get_offset_type(real_addr_frag1, state->types2[block2][frag2], offset1, info, other_info, size, snapshot1, &switch_type); + new_type_id2 = get_offset_type(real_addr_frag2, state->types2[block2][frag2], offset2, info, other_info, size, snapshot2, &switch_type); }else{ if(match_pairs){ match_equals(state, previous); -- 2.20.1