X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/6feb6e8bbb970e26a20a7c74234425bc7ebe0f6f..72680ab46a46b8f1ae2dbfb56581968206f4e3b1:/src/mc/mc_checkpoint.c diff --git a/src/mc/mc_checkpoint.c b/src/mc/mc_checkpoint.c index 6f6825a6ab..eb4cfd348e 100644 --- a/src/mc/mc_checkpoint.c +++ b/src/mc/mc_checkpoint.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2013. The SimGrid Team. +/* Copyright (c) 2008-2014. The SimGrid Team. * All rights reserved. */ /* This program is free software; you can redistribute it and/or modify it @@ -12,6 +12,7 @@ #include "mc_private.h" #include "xbt/module.h" #include +#include "../smpi/private.h" #include "xbt/mmalloc/mmprivate.h" @@ -43,9 +44,7 @@ static void MC_snapshot_stack_free_voidp(void *s){ } static void local_variable_free(local_variable_t v){ - xbt_free(v->frame); xbt_free(v->name); - xbt_free(v->type); xbt_free(v); } @@ -55,6 +54,7 @@ static void local_variable_free_voidp(void *v){ static void MC_region_destroy(mc_mem_region_t reg) { + //munmap(reg->data, reg->size); xbt_free(reg->data); xbt_free(reg); } @@ -67,6 +67,15 @@ void MC_free_snapshot(mc_snapshot_t snapshot){ xbt_free(snapshot->stack_sizes); xbt_dynar_free(&(snapshot->stacks)); xbt_dynar_free(&(snapshot->to_ignore)); + + if(snapshot->privatization_regions){ + size_t n = snapshot->nb_processes; + for(i=0; i!=n; ++i) { + MC_region_destroy(snapshot->privatization_regions[i]); + } + xbt_free(snapshot->privatization_regions); + } + xbt_free(snapshot); } @@ -79,8 +88,12 @@ static mc_mem_region_t MC_region_new(int type, void *start_addr, size_t size) 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 = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + //if(new_reg->data==MAP_FAILED) + //xbt_die("Could not mmap new memory for snapshot."); new_reg->data = xbt_malloc(size); memcpy(new_reg->data, start_addr, size); + //madvise(new_reg->data, size, MADV_MERGEABLE); XBT_DEBUG("New region : type : %d, data : %p (real addr %p), size : %zu", type, new_reg->data, start_addr, size); @@ -104,6 +117,7 @@ static void MC_snapshot_add_region(mc_snapshot_t snapshot, int type, void *start } static void MC_get_memory_regions(mc_snapshot_t snapshot){ + size_t i; void* start_heap = ((xbt_mheap_t)std_heap)->base; void* end_heap = ((xbt_mheap_t)std_heap)->breakval; @@ -111,7 +125,17 @@ static void MC_get_memory_regions(mc_snapshot_t snapshot){ 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); + if(!smpi_privatize_global_variables) { + MC_snapshot_add_region(snapshot, 2, mc_binary_info->start_rw, mc_binary_info->end_rw - mc_binary_info->start_rw); + snapshot->privatization_regions = NULL; + snapshot->privatization_index = -1; + } else { + snapshot->privatization_regions = xbt_new(mc_mem_region_t, SIMIX_process_count()); + for (i=0; i< SIMIX_process_count(); i++){ + snapshot->privatization_regions[i] = MC_region_new(-1, mappings[i], size_data_exe); + } + snapshot->privatization_index = loaded_page; + } } /** @brief Finds the range of the different memory segments and binary paths */ @@ -148,7 +172,7 @@ void MC_init_memory_map_info(){ } -/** \brief Fill/llokup the "subtype" field. +/** \brief Fill/lookup the "subtype" field. */ static void MC_resolve_subtype(mc_object_info_t info, dw_type_t type) { @@ -164,12 +188,11 @@ static void MC_resolve_subtype(mc_object_info_t info, dw_type_t type) { // 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); + dw_type_t subtype = xbt_dict_get_or_null(info->full_types_by_name, type->subtype->name); if(subtype!=NULL) { type->subtype = subtype; } - // TODO, support "switch type" (looking up the type in another lib) when possible } void MC_post_process_types(mc_object_info_t info) { @@ -189,7 +212,10 @@ void MC_post_process_types(mc_object_info_t info) { } } -/** \brief Fills the position of the .bss and .data sections. */ +/** \brief Fills the position of the segments (executable, read-only, read/write). + * + * TODO, use dl_iterate_phdr to be more robust + * */ void MC_find_object_address(memory_map_t maps, mc_object_info_t result) { unsigned int i = 0; @@ -207,7 +233,6 @@ void MC_find_object_address(memory_map_t maps, mc_object_info_t result) { 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; @@ -237,6 +262,69 @@ void MC_find_object_address(memory_map_t maps, mc_object_info_t result) { /************************************* Take Snapshot ************************************/ /****************************************************************************************/ +/** \brief Checks whether the variable is in scope for a given IP. + * + * A variable may be defined only from a given value of IP. + * + * \param var Variable description + * \param frame Scope description + * \param ip Instruction pointer + * \return true if the variable is valid + * */ +static bool mc_valid_variable(dw_variable_t var, dw_frame_t scope, const void* ip) { + // The variable is not yet valid: + if((const void*)((const char*) scope->low_pc + var->start_scope) > ip) + return false; + else + return true; +} + +static void mc_fill_local_variables_values(mc_stack_frame_t stack_frame, dw_frame_t scope, xbt_dynar_t result) { + void* ip = (void*) stack_frame->ip; + if(ip < scope->low_pc || ip>= scope->high_pc) + return; + + unsigned cursor = 0; + dw_variable_t current_variable; + xbt_dynar_foreach(scope->variables, cursor, current_variable){ + + if(!mc_valid_variable(current_variable, scope, (void*) stack_frame->ip)) + continue; + + int region_type; + if((long)stack_frame->ip > (long)mc_libsimgrid_info->start_exec) + region_type = 1; + else + region_type = 2; + + local_variable_t new_var = xbt_new0(s_local_variable_t, 1); + new_var->subprogram = stack_frame->frame; + new_var->ip = stack_frame->ip; + new_var->name = xbt_strdup(current_variable->name); + new_var->type = current_variable->type; + new_var->region= region_type; + + if(current_variable->address!=NULL) { + new_var->address = current_variable->address; + } else + if(current_variable->locations.size != 0){ + new_var->address = (void*) mc_dwarf_resolve_locations(¤t_variable->locations, + current_variable->object_info, + &(stack_frame->unw_cursor), (void*)stack_frame->frame_base, NULL); + } else { + xbt_die("No address"); + } + + xbt_dynar_push(result, &new_var); + } + + // Recursive processing of nested scopes: + dw_frame_t nested_scope = NULL; + xbt_dynar_foreach(scope->scopes, cursor, nested_scope) { + mc_fill_local_variables_values(stack_frame, nested_scope, result); + } +} + static xbt_dynar_t MC_get_local_variables_values(xbt_dynar_t stack_frames){ unsigned cursor1 = 0; @@ -244,39 +332,10 @@ static xbt_dynar_t MC_get_local_variables_values(xbt_dynar_t stack_frames){ xbt_dynar_t variables = xbt_dynar_new(sizeof(local_variable_t), local_variable_free_voidp); xbt_dynar_foreach(stack_frames,cursor1,stack_frame) { - - unsigned cursor2 = 0; - dw_variable_t current_variable; - xbt_dynar_foreach(stack_frame->frame->variables, cursor2, current_variable){ - - 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(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->region= region_type; - - /* 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); - - } + mc_fill_local_variables_values(stack_frame, stack_frame->frame, variables); } return variables; - } static void MC_stack_frame_free_voipd(void *s){ @@ -292,11 +351,13 @@ static xbt_dynar_t MC_unwind_stack_frames(void *stack_context) { unw_cursor_t c; - dw_frame_t test = MC_find_function_by_ip(&MC_unwind_stack_frames); - xbt_assert(test); + // TODO, check condition check (unw_init_local==0 means end of frame) + if(unw_init_local(&c, (unw_context_t *)stack_context)!=0) { + + xbt_die("Could not initialize stack unwinding"); + + } else while(1) { - int ret; - 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); @@ -317,28 +378,22 @@ static xbt_dynar_t MC_unwind_stack_frames(void *stack_context) { if(frame) { stack_frame->frame_name = xbt_strdup(frame->name); - - mc_object_info_t info = MC_ip_find_object_info((void*)ip); - - // This is the instruction pointer as present in the DWARF of the object: - // Relocated addresses are offset for shared objets and constant for executables objects. - // See DWARF4 spec 7.5 - unw_word_t normalized_ip; - if(info->flags & MC_OBJECT_INFO_EXECUTABLE) { - normalized_ip = ip; - } else { - void* base = MC_object_base_address(info); - normalized_ip = (unw_word_t) ip - (unw_word_t) base; - } - - stack_frame->frame_base = (unw_word_t)mc_find_frame_base(normalized_ip, frame, &c); + stack_frame->frame_base = (unw_word_t)mc_find_frame_base(frame, frame->object_info, &c); } else { stack_frame->frame_base = 0; + stack_frame->frame_name = NULL; } /* Stop before context switch with maestro */ if(frame!=NULL && frame->name!=NULL && !strcmp(frame->name, "smx_ctx_sysv_wrapper")) break; + + int ret = ret = unw_step(&c); + if(ret==0) { + xbt_die("Unexpected end of stack."); + } else if(ret<0) { + xbt_die("Error while unwinding stack."); + } } if(xbt_dynar_length(result) == 0){ @@ -445,6 +500,13 @@ mc_snapshot_t MC_take_snapshot(int num_state){ if(num_state > 0) MC_dump_checkpoint_ignore(snapshot); + // mprotect the region after zero-ing ignored parts: + /*size_t i; + for(i=0; i!=NB_REGIONS; ++i) { + mc_mem_region_t region = snapshot->regions[i]; + mprotect(region->data, region->size, PROT_READ); + }*/ + return snapshot; } @@ -452,9 +514,60 @@ mc_snapshot_t MC_take_snapshot(int num_state){ void MC_restore_snapshot(mc_snapshot_t snapshot){ unsigned int i; for(i=0; i < NB_REGIONS; i++){ - MC_region_restore(snapshot->regions[i]); + // For privatized, variables we decided it was not necessary to take the snapshot: + if(snapshot->regions[i]) + MC_region_restore(snapshot->regions[i]); + } + + if(snapshot->privatization_regions) { + for (i=0; i< SIMIX_process_count(); i++){ + if(snapshot->privatization_regions[i]) { + MC_region_restore(snapshot->privatization_regions[i]); + } + } + switch_data_segment(snapshot->privatization_index); + } +} + +void* mc_translate_address(uintptr_t addr, mc_snapshot_t snapshot) { + + // If not in a process state/clone: + if(!snapshot) { + return (uintptr_t*) addr; + } + + // If it is in a snapshot: + for(size_t i=0; i!=NB_REGIONS; ++i) { + mc_mem_region_t region = snapshot->regions[i]; + uintptr_t start = (uintptr_t) region->start_addr; + uintptr_t end = start + region->size; + + // The address is in this region: + if(addr >= start && addr < end) { + uintptr_t offset = addr - start; + return (void*) ((uintptr_t)region->data + offset); + } + + } + + // It is not in a snapshot: + return (void*) addr; +} + +uintptr_t mc_untranslate_address(void* addr, mc_snapshot_t snapshot) { + if(!snapshot) { + return (uintptr_t) addr; + } + + for(size_t i=0; i!=NB_REGIONS; ++i) { + mc_mem_region_t region = snapshot->regions[i]; + if(addr>=region->data && addr<=(void*)(((char*)region->data)+region->size)) { + size_t offset = (size_t) ((char*) addr - (char*) region->data); + return ((uintptr_t) region->start_addr) + offset; + } } + return (uintptr_t) addr; } mc_snapshot_t SIMIX_pre_mc_snapshot(smx_simcall_t simcall){