X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/63879715597c2d861efa03bef390b9c7e2ede8e8..4e194aa6e85bdaafc9d69876bd7d2e79c74d5502:/src/mc/mc_process.c diff --git a/src/mc/mc_process.c b/src/mc/mc_process.c index 207efa9c83..9c89adaa78 100644 --- a/src/mc/mc_process.c +++ b/src/mc/mc_process.c @@ -14,9 +14,18 @@ #include +#include +#include + +#include + #include "mc_process.h" #include "mc_object_info.h" #include "mc_address_space.h" +#include "mc_unw.h" +#include "mc_snapshot.h" +#include "mc_ignore.h" +#include "mc_smx.h" XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_process, mc, "MC process information"); @@ -24,17 +33,36 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_process, mc, static void MC_process_init_memory_map_info(mc_process_t process); static void MC_process_open_memory_file(mc_process_t process); -static s_mc_address_space_class_t mc_process_class = { - .read = (void*) &MC_process_read +// ***** Destructor callbacks + +// ***** mc_address_space methods for mc_process + +static mc_process_t MC_process_get_process(mc_process_t p) { + return p; +} + +static const s_mc_address_space_class_t mc_process_class = { + .read = (void*) &MC_process_read, + .get_process = (void*) MC_process_get_process }; -void MC_process_init(mc_process_t process, pid_t pid) +bool MC_is_process(mc_address_space_t p) +{ + return p->address_space_class == &mc_process_class; +} + +// ***** mc_process + +void MC_process_init(mc_process_t process, pid_t pid, int sockfd) { process->address_space.address_space_class = &mc_process_class; process->process_flags = MC_PROCESS_NO_FLAG; + process->socket = sockfd; process->pid = pid; if (pid==getpid()) process->process_flags |= MC_PROCESS_SELF_FLAG; + process->running = true; + process->status = 0; process->memory_map = MC_get_memory_map(pid); process->memory_file = -1; process->cache_flags = 0; @@ -52,6 +80,20 @@ void MC_process_init(mc_process_t process, pid_t pid) MC_process_read(process, MC_ADDRESS_SPACE_READ_FLAGS_NONE, &process->heap_address, std_heap_var->address, sizeof(struct mdesc*), MC_PROCESS_INDEX_DISABLED); + + process->smx_process_infos = MC_smx_process_info_list_new(); + process->smx_old_process_infos = MC_smx_process_info_list_new(); + + process->checkpoint_ignore = MC_checkpoint_ignore_new(); + + process->unw_addr_space = unw_create_addr_space(&mc_unw_accessors , __BYTE_ORDER); + if (process->process_flags & MC_PROCESS_SELF_FLAG) { + process->unw_underlying_addr_space = unw_local_addr_space; + process->unw_underlying_context = NULL; + } else { + process->unw_underlying_addr_space = unw_create_addr_space(&mc_unw_vmread_accessors, __BYTE_ORDER); + process->unw_underlying_context = _UPT_create(pid); + } } void MC_process_clear(mc_process_t process) @@ -66,6 +108,11 @@ void MC_process_clear(mc_process_t process) process->maestro_stack_start = NULL; process->maestro_stack_end = NULL; + xbt_dynar_free(&process->checkpoint_ignore); + + xbt_dynar_free(&process->smx_process_infos); + xbt_dynar_free(&process->smx_old_process_infos); + size_t i; for (i=0; i!=process->object_infos_size; ++i) { MC_free_object_info(&process->object_infos[i]); @@ -77,6 +124,16 @@ void MC_process_clear(mc_process_t process) close(process->memory_file); } + if (process->unw_underlying_addr_space != unw_local_addr_space) { + unw_destroy_addr_space(process->unw_underlying_addr_space); + _UPT_destroy(process->unw_underlying_context); + } + process->unw_underlying_context = NULL; + process->unw_underlying_addr_space = NULL; + + unw_destroy_addr_space(process->unw_addr_space); + process->unw_addr_space = NULL; + process->cache_flags = 0; free(process->heap); @@ -91,8 +148,7 @@ void MC_process_refresh_heap(mc_process_t process) assert(!MC_process_is_self(process)); // Read/dereference/refresh the std_heap pointer: if (!process->heap) { - xbt_mheap_t oldheap = mmalloc_get_current_heap(); - MC_SET_MC_HEAP; + xbt_mheap_t oldheap = mmalloc_set_current_heap(mc_heap); process->heap = malloc(sizeof(struct mdesc)); mmalloc_set_current_heap(oldheap); } @@ -110,11 +166,10 @@ void MC_process_refresh_malloc_info(mc_process_t process) // Refresh process->heapinfo: size_t malloc_info_bytesize = process->heap->heaplimit * sizeof(malloc_info); - xbt_mheap_t oldheap = mmalloc_get_current_heap(); - MC_SET_MC_HEAP; + xbt_mheap_t heap = mmalloc_set_current_heap(mc_heap); process->heap_info = (malloc_info*) realloc(process->heap_info, malloc_info_bytesize); - mmalloc_set_current_heap(oldheap); + mmalloc_set_current_heap(heap); MC_process_read(process, MC_ADDRESS_SPACE_READ_FLAGS_NONE, process->heap_info, @@ -134,6 +189,7 @@ const char* FILTERED_LIBS[] = { "libunwind", "libunwind-x86_64", "libunwind-x86", + "libunwind-ptrace", "libdw", "libdl", "librt", @@ -188,7 +244,7 @@ static char* MC_get_lib_name(const char* pathname, struct s_mc_memory_map_re* re /** @brief Finds the range of the different memory segments and binary paths */ static void MC_process_init_memory_map_info(mc_process_t process) { - XBT_INFO("Get debug information ..."); + XBT_DEBUG("Get debug information ..."); process->maestro_stack_start = NULL; process->maestro_stack_end = NULL; process->object_infos = NULL; @@ -265,10 +321,10 @@ static void MC_process_init_memory_map_info(mc_process_t process) for (i=0; i!=process->object_infos_size; ++i) MC_post_process_object_info(process, process->object_infos[i]); - xbt_assert(process->maestro_stack_start, "maestro_stack_start"); - xbt_assert(process->maestro_stack_end, "maestro_stack_end"); + xbt_assert(process->maestro_stack_start, "Did not find maestro_stack_start"); + xbt_assert(process->maestro_stack_end, "Did not find maestro_stack_end"); - XBT_INFO("Get debug information done !"); + XBT_DEBUG("Get debug information done !"); } mc_object_info_t MC_process_find_object_info(mc_process_t process, const void *addr) @@ -322,34 +378,64 @@ dw_variable_t MC_process_find_variable_by_name(mc_process_t process, const char* { const size_t n = process->object_infos_size; size_t i; + + // First lookup the variable in the executable shared object. + // A global variable used directly by the executable code from a library + // is reinstanciated in the executable memory .data/.bss. + // We need to look up the variable in the execvutable first. + if (process->binary_info) { + mc_object_info_t info = process->binary_info; + dw_variable_t var = MC_file_object_info_find_variable_by_name(info, name); + if (var) + return var; + } + for (i=0; i!=n; ++i) { mc_object_info_t info =process->object_infos[i]; dw_variable_t var = MC_file_object_info_find_variable_by_name(info, name); if (var) return var; } + return NULL; } +void MC_process_read_variable(mc_process_t process, const char* name, void* target, size_t size) +{ + dw_variable_t var = MC_process_find_variable_by_name(process, name); + if (!var->address) + xbt_die("No simple location for this variable"); + if (!var->type->full_type) + xbt_die("Partial type for %s, cannot check size", name); + if (var->type->full_type->byte_size != size) + xbt_die("Unexpected size for %s (expected %zi, was %zi)", + name, size, (size_t) var->type->full_type->byte_size); + MC_process_read(process, MC_PROCESS_NO_FLAG, target, var->address, size, + MC_PROCESS_INDEX_ANY); +} + // ***** Memory access -static void MC_process_open_memory_file(mc_process_t process) +int MC_process_vm_open(pid_t pid, int flags) { - if (MC_process_is_self(process) || process->memory_file >= 0) - return; - const size_t buffer_size = 30; char buffer[buffer_size]; - int res = snprintf(buffer, buffer_size, "/proc/%lli/mem", (long long) process->pid); - if (res < 0 || res>= buffer_size) { - XBT_ERROR("Could not open memory file descriptor for process %lli", - (long long) process->pid); - return; + int res = snprintf(buffer, buffer_size, "/proc/%lli/mem", (long long) pid); + if (res < 0 || res >= buffer_size) { + errno = ENAMETOOLONG; + return -1; } + return open(buffer, flags); +} + +static void MC_process_open_memory_file(mc_process_t process) +{ + if (MC_process_is_self(process) || process->memory_file >= 0) + return; - int fd = open(buffer, O_RDWR); + int fd = MC_process_vm_open(process->pid, O_RDWR); if (fd<0) - xbt_die("Could not initialise memory access for remote process"); + xbt_die("Could not open file for process virtual address space"); process->memory_file = fd; } @@ -421,6 +507,24 @@ const void* MC_process_read(mc_process_t process, e_adress_space_read_flags_t fl } } +const void* MC_process_read_simple(mc_process_t process, + void* local, const void* remote, size_t len) +{ + e_adress_space_read_flags_t flags = MC_PROCESS_NO_FLAG; + int index = MC_PROCESS_INDEX_ANY; + MC_process_read(process, flags, local, remote, len, index); + return local; +} + +const void* MC_process_read_dynar_element(mc_process_t process, + void* local, const void* remote_dynar, size_t i) +{ + s_xbt_dynar_t d; + MC_process_read_simple(process, &d, remote_dynar, sizeof(d)); + MC_process_read_simple(process, local, xbt_dynar_get_ptr(&d, i), i); + return local; +} + void MC_process_write(mc_process_t process, const void* local, void* remote, size_t len) { if (MC_process_is_self(process)) { @@ -431,6 +535,16 @@ void MC_process_write(mc_process_t process, const void* local, void* remote, siz } } +unsigned long MC_process_read_dynar_length(mc_process_t process, const void* remote_dynar) +{ + if (!remote_dynar) + return 0; + unsigned long res; + MC_process_read_simple(process, &res, + &((xbt_dynar_t)remote_dynar)->used, sizeof(res)); + return res; +} + static pthread_once_t zero_buffer_flag = PTHREAD_ONCE_INIT; static const void* zero_buffer; static const int zero_buffer_size = 10 * 4096; @@ -460,3 +574,35 @@ void MC_process_clear_memory(mc_process_t process, void* remote, size_t len) } } } + +void MC_simcall_handle(smx_simcall_t req, int value) +{ + if (MC_process_is_self(&mc_model_checker->process)) { + SIMIX_simcall_handle(req, value); + return; + } + + MC_process_smx_refresh(&mc_model_checker->process); + + unsigned i; + mc_smx_process_info_t pi = NULL; + + xbt_dynar_foreach_ptr(mc_model_checker->process.smx_process_infos, i, pi) { + smx_process_t p = (smx_process_t) pi->address; + if (req == &pi->copy.simcall) { + smx_simcall_t real_req = &p->simcall; + // TODO, use a remote call + SIMIX_simcall_handle(real_req, value); + return; + } + } + + // Check (remove afterwards): + xbt_dynar_foreach_ptr(mc_model_checker->process.smx_process_infos, i, pi) { + smx_process_t p = (smx_process_t) pi->address; + if (req == &p->simcall) + xbt_die("The real simcall was passed. We expected the local copy."); + } + + xbt_die("Could not find the request"); +}