Add a `address_space`, superclass of `process` and `snapshot`.
In order to do this, the contract of MC_process_read and
MC_snapshot_read has been uniformized:
* the order of arguments has been harmonized;
* a new flag MC_ADDRESS_SPACE_READ_FLAGS_LAZY is used to avoid copy
when the data is in the current memory;
* MC_NO_PROCESS_INDEX has been renamed into MC_PROCESS_INDEX_MISSING;
* MC_ANY_PROCESS_INDEX has been renamed into MC_PROCESS_INDEX_ANY;
* MC_PROCESS_INDEX_DISABLED is used to access the raw address space
(without privatisation support);
* `const void*` is used instead of `void*` when it possible.
Soem cleanup things are still to be done:
* remove special NULL handling;
* add support for SMPI privatization in the process object.
)
set(MC_SRC
+ src/mc/mc_address_space.h
+ src/mc/mc_address_space.c
src/mc/mc_forward.h
src/mc/mc_process.h
src/mc/mc_process.c
int mmalloc_compare_heap(struct s_mc_snapshot* snapshot1, struct s_mc_snapshot* snapshot2);
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(int process_index, void *area1, void* area2, struct s_mc_snapshot* snapshot1, struct s_mc_snapshot* snapshot2, xbt_dynar_t previous, struct s_dw_type *type, int pointer_level);
+int compare_heap_area(int process_index, const void *area1, const void* area2, struct s_mc_snapshot* snapshot1, struct s_mc_snapshot* snapshot2, xbt_dynar_t previous, struct s_dw_type *type, int pointer_level);
void reset_heap_information(void);
size_t mmalloc_get_bytes_used(xbt_mheap_t);
--- /dev/null
+/* Copyright (c) 2008-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 "mc_address_space.h"
--- /dev/null
+/* Copyright (c) 2008-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. */
+
+#ifndef MC_ADDRESS_SPACE_H
+#define MC_ADDRESS_SPACE_H
+
+#include <stdint.h>
+
+#include "mc_forward.h"
+
+// ***** Data types
+
+typedef enum e_adress_space_read_flags {
+ MC_ADDRESS_SPACE_READ_FLAGS_NONE = 0,
+
+ /** Avoid a copy for when the data is available in the current process.
+ *
+ * In this case, the return value of a MC_address_space_read might
+ * be different from the provided buffer.
+ */
+ MC_ADDRESS_SPACE_READ_FLAGS_LAZY = 1
+} e_adress_space_read_flags_t;
+
+/** Process index used when no process is available
+ *
+ * The expected behaviour is that if a process index is needed it will fail.
+ * */
+#define MC_PROCESS_INDEX_MISSING -1
+
+#define MC_PROCESS_INDEX_DISABLED -2
+
+/** Process index when any process is suitable
+ *
+ * We could use a special negative value in the future.
+ */
+#define MC_PROCESS_INDEX_ANY 0
+
+// ***** Class definition
+
+typedef struct s_mc_address_space s_mc_address_space_t, *mc_address_space_t;
+typedef struct s_mc_address_space_class s_mc_address_space_class_t, *mc_address_space_class_t;
+
+struct s_mc_address_space_class {
+ const void* (*read)(
+ mc_address_space_t address_space, e_adress_space_read_flags_t flags,
+ void* target, const void* addr, size_t size,
+ int process_index);
+};
+
+/** Base class for an address space (process and snapshot)
+ */
+struct s_mc_address_space {
+ mc_address_space_class_t address_space_class;
+};
+
+// ***** Virtual/non-final methods
+
+/** Read data from the given address space */
+static inline __attribute__((always_inline))
+const void* MC_address_space_read(
+ mc_address_space_t address_space, e_adress_space_read_flags_t flags,
+ void* target, const void* addr, size_t size,
+ int process_index)
+{
+ return address_space->address_space_class->read(
+ address_space, flags, target, addr, size,
+ process_index);
+}
+
+#endif
region->permanent_addr = permanent_addr;
region->size = size;
region->flat.data = xbt_malloc(size);
- MC_process_read(&mc_model_checker->process, region->flat.data, permanent_addr, size);
+ MC_process_read(&mc_model_checker->process, MC_ADDRESS_SPACE_READ_FLAGS_NONE,
+ region->flat.data, permanent_addr, size,
+ MC_PROCESS_INDEX_DISABLED);
XBT_DEBUG("New region : type : %d, data : %p (real addr %p), size : %zu",
region_type, region->flat.data, permanent_addr, size);
return region;
} else
#endif
{
- snapshot->privatization_index = MC_NO_PROCESS_INDEX;
+ snapshot->privatization_index = MC_PROCESS_INDEX_MISSING;
}
}
closedir (fd_dir);
}
+static s_mc_address_space_class_t mc_snapshot_class = {
+ .read = (void*) &MC_snapshot_read
+};
+
mc_snapshot_t MC_take_snapshot(int num_state)
{
mc_process_t mc_process = &mc_model_checker->process;
mc_snapshot_t snapshot = xbt_new0(s_mc_snapshot_t, 1);
+ snapshot->process = mc_process;
+ snapshot->address_space.address_space_class = &mc_snapshot_class;
snapshot->enabled_processes = xbt_dynar_new(sizeof(int), NULL);
smx_process_t process;
case DW_TAG_enumeration_type:
case DW_TAG_union_type:
{
- return mc_snapshot_region_memcmp(
+ return MC_snapshot_region_memcmp(
real_area1, region1, real_area2, region2,
type->byte_size) != 0;
}
case DW_TAG_reference_type:
case DW_TAG_rvalue_reference_type:
{
- void* addr_pointed1 = mc_snapshot_read_pointer_region(real_area1, region1);
- void* addr_pointed2 = mc_snapshot_read_pointer_region(real_area2, region2);
+ 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);
case DW_TAG_class_type:
xbt_dynar_foreach(type->members, cursor, member) {
void *member1 =
- mc_member_resolve(real_area1, type, member, snapshot1, process_index);
+ mc_member_resolve(real_area1, type, member, (mc_address_space_t) snapshot1, process_index);
void *member2 =
- mc_member_resolve(real_area2, type, member, snapshot2, process_index);
+ mc_member_resolve(real_area2, type, member, (mc_address_space_t) snapshot2, process_index);
mc_mem_region_t subregion1 = mc_get_region_hinted(member1, snapshot1, process_index, region1);
mc_mem_region_t subregion2 = mc_get_region_hinted(member2, snapshot2, process_index, region2);
res =
#endif
/* Init heap information used in heap comparison algorithm */
- xbt_mheap_t heap1 = (xbt_mheap_t) mc_snapshot_read(process->heap_address, s1, MC_NO_PROCESS_INDEX,
- alloca(sizeof(struct mdesc)), sizeof(struct mdesc));
- xbt_mheap_t heap2 = (xbt_mheap_t) mc_snapshot_read(process->heap_address, s2, MC_NO_PROCESS_INDEX,
- alloca(sizeof(struct mdesc)), sizeof(struct mdesc));
+ xbt_mheap_t heap1 = (xbt_mheap_t) MC_snapshot_read(
+ s1, MC_ADDRESS_SPACE_READ_FLAGS_LAZY,
+ alloca(sizeof(struct mdesc)), process->heap_address, sizeof(struct mdesc),
+ MC_PROCESS_INDEX_MISSING);
+ xbt_mheap_t heap2 = (xbt_mheap_t) MC_snapshot_read(
+ s2, MC_ADDRESS_SPACE_READ_FLAGS_LAZY,
+ alloca(sizeof(struct mdesc)), process->heap_address, sizeof(struct mdesc),
+ MC_PROCESS_INDEX_MISSING);
res_init = init_heap_information(heap1, heap2, s1->to_ignore, s2->to_ignore);
if (res_init == -1) {
#ifdef MC_DEBUG
/* Compare global variables */
is_diff =
- compare_global_variables(region1->object_info, MC_NO_PROCESS_INDEX,
+ compare_global_variables(region1->object_info, MC_ADDRESS_SPACE_READ_FLAGS_NONE,
region1, region2,
s1, s2);
}
static ssize_t heap_comparison_ignore_size(xbt_dynar_t ignore_list,
- void *address)
+ const void *address)
{
unsigned int cursor = 0;
return -1;
}
-static int is_stack(void *address)
+static int is_stack(const void *address)
{
unsigned int cursor = 0;
stack_region_t stack;
void* heapinfo_address = &((xbt_mheap_t) process->heap_address)->heapinfo;
// This is in snapshot do not use them directly:
- malloc_info* heapinfos1 = mc_snapshot_read_pointer(heapinfo_address, snapshot1, MC_NO_PROCESS_INDEX);
- malloc_info* heapinfos2 = mc_snapshot_read_pointer(heapinfo_address, snapshot2, MC_NO_PROCESS_INDEX);
+ const malloc_info* heapinfos1 = MC_snapshot_read_pointer(snapshot1, heapinfo_address, MC_PROCESS_INDEX_MISSING);
+ const malloc_info* heapinfos2 = MC_snapshot_read_pointer(snapshot2, heapinfo_address, MC_PROCESS_INDEX_MISSING);
while (i1 <= state->heaplimit) {
- malloc_info* heapinfo1 = mc_snapshot_read_region(&heapinfos1[i1], heap_region1, &heapinfo_temp1, sizeof(malloc_info));
- malloc_info* heapinfo2 = mc_snapshot_read_region(&heapinfos2[i1], heap_region2, &heapinfo_temp2, sizeof(malloc_info));
+ const malloc_info* heapinfo1 = MC_region_read(heap_region1, &heapinfo_temp1, &heapinfos1[i1], sizeof(malloc_info));
+ const malloc_info* heapinfo2 = MC_region_read(heap_region2, &heapinfo_temp2, &heapinfos2[i1], sizeof(malloc_info));
if (heapinfo1->type == MMALLOC_TYPE_FREE || heapinfo1->type == MMALLOC_TYPE_HEAPINFO) { /* Free block */
i1 ++;
(char *) ((xbt_mheap_t) state->s_heap)->heapbase));
res_compare =
- compare_heap_area(MC_NO_PROCESS_INDEX, addr_block1, addr_block2, snapshot1, snapshot2,
+ compare_heap_area(MC_PROCESS_INDEX_MISSING, addr_block1, addr_block2, snapshot1, snapshot2,
NULL, NULL, 0);
if (res_compare != 1) {
continue;
}
- malloc_info* heapinfo2b = mc_snapshot_read_region(&heapinfos2[i2], heap_region2, &heapinfo_temp2b, sizeof(malloc_info));
+ const malloc_info* heapinfo2b = MC_region_read(heap_region2, &heapinfo_temp2b, &heapinfos2[i2], sizeof(malloc_info));
if (heapinfo2b->type != MMALLOC_TYPE_UNFRAGMENTED) {
i2++;
}
res_compare =
- compare_heap_area(MC_NO_PROCESS_INDEX, addr_block1, addr_block2, snapshot1, snapshot2,
+ compare_heap_area(MC_PROCESS_INDEX_MISSING, addr_block1, addr_block2, snapshot1, snapshot2,
NULL, NULL, 0);
if (res_compare != 1) {
(j1 << heapinfo2->type));
res_compare =
- compare_heap_area(MC_NO_PROCESS_INDEX, addr_frag1, addr_frag2, snapshot1, snapshot2,
+ compare_heap_area(MC_PROCESS_INDEX_MISSING, addr_frag1, addr_frag2, snapshot1, snapshot2,
NULL, NULL, 0);
if (res_compare != 1)
while (i2 <= state->heaplimit && !equal) {
- malloc_info* heapinfo2b = mc_snapshot_read_region(&heapinfos2[i2], heap_region2, &heapinfo_temp2b, sizeof(malloc_info));
+ const malloc_info* heapinfo2b = MC_region_read(heap_region2, &heapinfo_temp2b, &heapinfos2[i2], sizeof(malloc_info));
if (heapinfo2b->type == MMALLOC_TYPE_FREE || heapinfo2b->type == MMALLOC_TYPE_HEAPINFO) {
i2 ++;
(j2 << heapinfo2b->type));
res_compare =
- compare_heap_area(MC_NO_PROCESS_INDEX, addr_frag1, addr_frag2, snapshot2, snapshot2,
+ compare_heap_area(MC_PROCESS_INDEX_MISSING, addr_frag1, addr_frag2, snapshot2, snapshot2,
NULL, NULL, 0);
if (res_compare != 1) {
size_t i = 1, j = 0;
for(i = 1; i <= state->heaplimit; i++) {
- malloc_info* heapinfo1 = mc_snapshot_read_region(&heapinfos1[i], heap_region1, &heapinfo_temp1, sizeof(malloc_info));
+ const malloc_info* heapinfo1 = MC_region_read(heap_region1, &heapinfo_temp1, &heapinfos1[i], sizeof(malloc_info));
if (heapinfo1->type == MMALLOC_TYPE_UNFRAGMENTED) {
if (i1 == state->heaplimit) {
if (heapinfo1->busy_block.busy_size > 0) {
XBT_DEBUG("Number of blocks/fragments not found in heap1 : %d", nb_diff1);
for (i=1; i <= state->heaplimit; i++) {
- malloc_info* heapinfo2 = mc_snapshot_read_region(&heapinfos2[i], heap_region2, &heapinfo_temp2, sizeof(malloc_info));
+ const malloc_info* heapinfo2 = MC_region_read(heap_region2, &heapinfo_temp2, &heapinfos2[i], sizeof(malloc_info));
if (heapinfo2->type == MMALLOC_TYPE_UNFRAGMENTED) {
if (i1 == state->heaplimit) {
if (heapinfo2->busy_block.busy_size > 0) {
* @param check_ignore
*/
static int compare_heap_area_without_type(struct s_mc_diff *state, int process_index,
- void *real_area1, void *real_area2,
+ const void *real_area1, const void *real_area2,
mc_snapshot_t snapshot1,
mc_snapshot_t snapshot2,
xbt_dynar_t previous, int size,
mc_process_t process = &mc_model_checker->process;
int i = 0;
- void *addr_pointed1, *addr_pointed2;
+ const void *addr_pointed1, *addr_pointed2;
int pointer_align, res_compare;
ssize_t ignore1, ignore2;
}
}
- if (mc_snapshot_region_memcmp(((char *) real_area1) + i, heap_region1, ((char *) real_area2) + i, heap_region2, 1) != 0) {
+ if (MC_snapshot_region_memcmp(((char *) real_area1) + i, heap_region1, ((char *) real_area2) + i, heap_region2, 1) != 0) {
pointer_align = (i / sizeof(void *)) * sizeof(void *);
- addr_pointed1 = mc_snapshot_read_pointer((char *) real_area1 + pointer_align, snapshot1, process_index);
- addr_pointed2 = mc_snapshot_read_pointer((char *) real_area2 + pointer_align, snapshot2, process_index);
+ addr_pointed1 = MC_snapshot_read_pointer(snapshot1, (char *) real_area1 + pointer_align, process_index);
+ addr_pointed2 = MC_snapshot_read_pointer(snapshot2, (char *) real_area2 + pointer_align, process_index);
if (addr_pointed1 > process->maestro_stack_start
&& addr_pointed1 < process->maestro_stack_end
* @return 0 (same), 1 (different), -1 (unknown)
*/
static int compare_heap_area_with_type(struct s_mc_diff *state, int process_index,
- void *real_area1, void *real_area2,
+ const void *real_area1, const void *real_area2,
mc_snapshot_t snapshot1,
mc_snapshot_t snapshot2,
xbt_dynar_t previous, dw_type_t type,
int res, elm_size, i;
unsigned int cursor = 0;
dw_type_t member;
- void *addr_pointed1, *addr_pointed2;;
+ const void *addr_pointed1, *addr_pointed2;;
mc_mem_region_t heap_region1 = MC_get_heap_region(snapshot1);
mc_mem_region_t heap_region2 = MC_get_heap_region(snapshot2);
if (real_area1 == real_area2)
return -1;
else
- return (mc_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, area_size) != 0);
+ 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);
+ return (MC_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, type->byte_size) != 0);
}
}
break;
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);
+ return (MC_snapshot_region_memcmp(real_area1, heap_region1, real_area2, heap_region2, type->byte_size) != 0);
break;
case DW_TAG_typedef:
case DW_TAG_const_type:
case DW_TAG_rvalue_reference_type:
case DW_TAG_pointer_type:
if (type->subtype && type->subtype->type == DW_TAG_subroutine_type) {
- addr_pointed1 = mc_snapshot_read_pointer(real_area1, snapshot1, process_index);
- addr_pointed2 = mc_snapshot_read_pointer(real_area2, snapshot2, process_index);
+ addr_pointed1 = MC_snapshot_read_pointer(snapshot1, real_area1, process_index);
+ addr_pointed2 = MC_snapshot_read_pointer(snapshot2, real_area2, process_index);
return (addr_pointed1 != addr_pointed2);;
} else {
pointer_level++;
if (pointer_level > 1) { /* Array of pointers */
for (i = 0; i < (area_size / sizeof(void *)); i++) {
- addr_pointed1 = mc_snapshot_read_pointer((char*) real_area1 + i * sizeof(void *), snapshot1, process_index);
- addr_pointed2 = mc_snapshot_read_pointer((char*) real_area2 + i * sizeof(void *), snapshot2, process_index);
+ addr_pointed1 = MC_snapshot_read_pointer(snapshot1, (char*) real_area1 + i * sizeof(void *), process_index);
+ addr_pointed2 = MC_snapshot_read_pointer(snapshot2, (char*) real_area2 + i * sizeof(void *), process_index);
if (addr_pointed1 > state->s_heap
&& addr_pointed1 < mc_snapshot_get_heap_end(snapshot1)
&& addr_pointed2 > state->s_heap
return res;
}
} else {
- addr_pointed1 = mc_snapshot_read_pointer(real_area1, snapshot1, process_index);
- addr_pointed2 = mc_snapshot_read_pointer(real_area2, snapshot2, process_index);
+ addr_pointed1 = MC_snapshot_read_pointer(snapshot1, real_area1, process_index);
+ addr_pointed2 = MC_snapshot_read_pointer(snapshot2, real_area2, process_index);
if (addr_pointed1 > state->s_heap
&& addr_pointed1 < mc_snapshot_get_heap_end(snapshot1)
&& addr_pointed2 > state->s_heap
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, process_index);
+ mc_member_resolve(real_area1, type, member, (mc_address_space_t) snapshot1, process_index);
char *real_member2 =
- mc_member_resolve(real_area2, type, member, snapshot2, process_index);
+ mc_member_resolve(real_area2, type, member, (mc_address_space_t) snapshot2, process_index);
res =
compare_heap_area_with_type(state, process_index, real_member1, real_member2,
snapshot1, snapshot2,
return member->subtype;
} else {
char *real_member =
- mc_member_resolve(real_base_address, type, member, snapshot, process_index);
+ mc_member_resolve(real_base_address, type, member, (mc_address_space_t) snapshot, process_index);
if (real_member - (char *) real_base_address == offset)
return member->subtype;
}
* @param pointer_level
* @return 0 (same), 1 (different), -1
*/
-int compare_heap_area(int process_index, void *area1, void *area2, mc_snapshot_t snapshot1,
+int compare_heap_area(int process_index, const void *area1, const void *area2, mc_snapshot_t snapshot1,
mc_snapshot_t snapshot2, xbt_dynar_t previous,
dw_type_t type, int pointer_level)
{
// This is the address of std_heap->heapinfo in the application process:
void* heapinfo_address = &((xbt_mheap_t) process->heap_address)->heapinfo;
- malloc_info* heapinfos1 = mc_snapshot_read_pointer(heapinfo_address, snapshot1, process_index);
- malloc_info* heapinfos2 = mc_snapshot_read_pointer(heapinfo_address, snapshot2, process_index);
+ const malloc_info* heapinfos1 = MC_snapshot_read_pointer(snapshot1, heapinfo_address, process_index);
+ const malloc_info* heapinfos2 = MC_snapshot_read_pointer(snapshot2, heapinfo_address, process_index);
malloc_info heapinfo_temp1, heapinfo_temp2;
mc_mem_region_t heap_region1 = MC_get_heap_region(snapshot1);
mc_mem_region_t heap_region2 = MC_get_heap_region(snapshot2);
- malloc_info* heapinfo1 = mc_snapshot_read_region(&heapinfos1[block1], heap_region1, &heapinfo_temp1, sizeof(malloc_info));
- malloc_info* heapinfo2 = mc_snapshot_read_region(&heapinfos2[block2], heap_region2, &heapinfo_temp2, sizeof(malloc_info));
+ const malloc_info* heapinfo1 = MC_region_read(heap_region1, &heapinfo_temp1, &heapinfos1[block1], sizeof(malloc_info));
+ const malloc_info* heapinfo2 = MC_region_read(heap_region2, &heapinfo_temp2, &heapinfos2[block2], sizeof(malloc_info));
if ((heapinfo1->type == MMALLOC_TYPE_FREE || heapinfo1->type==MMALLOC_TYPE_HEAPINFO)
&& (heapinfo2->type == MMALLOC_TYPE_FREE || heapinfo2->type ==MMALLOC_TYPE_HEAPINFO)) {
#include <elfutils/libdw.h>
#include "mc_object_info.h"
-#include "mc_snapshot.h"
#include "mc_private.h"
static int mc_dwarf_push_value(mc_expression_state_t state, Dwarf_Off value)
{
// Computed address:
uintptr_t address = (uintptr_t) state->stack[state->stack_size - 1];
- uintptr_t temp;
- uintptr_t* res = (uintptr_t*) mc_snapshot_read((void*) address, state->snapshot, state->process_index, &temp, sizeof(uintptr_t));
- state->stack[state->stack_size - 1] = *res;
+ uintptr_t value;
+ if (state->address_space) {
+ uintptr_t temp;
+ const uintptr_t* res = (uintptr_t*) MC_address_space_read(
+ state->address_space, MC_ADDRESS_SPACE_READ_FLAGS_LAZY,
+ &temp, (const void*) address, sizeof(uintptr_t), state->process_index);
+ value = *res;
+ }
+ else {
+ // TODO, use a mc_process representing the current process instead of this
+ value = *(const uintptr_t*) address;
+ }
+ state->stack[state->stack_size - 1] = value;
}
break;
mc_object_info_t object_info,
unw_cursor_t * c,
void *frame_pointer_address,
- mc_snapshot_t snapshot, int process_index)
+ mc_address_space_t address_space, int process_index)
{
s_mc_expression_state_t state;
memset(&state, 0, sizeof(s_mc_expression_state_t));
state.frame_base = frame_pointer_address;
state.cursor = c;
- state.snapshot = snapshot;
+ state.address_space = address_space;
state.object_info = object_info;
state.process_index = process_index;
mc_object_info_t object_info,
unw_cursor_t * c,
void *frame_pointer_address,
- mc_snapshot_t snapshot, int process_index)
+ mc_address_space_t address_space, int process_index)
{
unw_word_t ip = 0;
if (expression) {
mc_dwarf_resolve_location(location,
expression, object_info, c,
- frame_pointer_address, snapshot, process_index);
+ frame_pointer_address, address_space, process_index);
} else {
xbt_die("Could not resolve location");
}
#include "mc_interface.h"
#include "mc_object_info.h"
#include "mc_forward.h"
+#include "mc_address_space.h"
SG_BEGIN_DECL()
}
}
-void mc_dwarf_resolve_location(mc_location_t location, mc_expression_t expression, mc_object_info_t object_info, unw_cursor_t* c, void* frame_pointer_address, mc_snapshot_t snapshot, int process_index);
-void mc_dwarf_resolve_locations(mc_location_t location, mc_location_list_t locations, mc_object_info_t object_info, unw_cursor_t* c, void* frame_pointer_address, mc_snapshot_t snapshot, int process_index);
+void mc_dwarf_resolve_location(mc_location_t location, mc_expression_t expression, mc_object_info_t object_info, unw_cursor_t* c, void* frame_pointer_address, mc_address_space_t address_space, int process_index);
+void mc_dwarf_resolve_locations(mc_location_t location, mc_location_list_t locations, mc_object_info_t object_info, unw_cursor_t* c, void* frame_pointer_address, mc_address_space_t address_space, int process_index);
void mc_dwarf_expression_clear(mc_expression_t expression);
void mc_dwarf_expression_init(mc_expression_t expression, size_t len, Dwarf_Op* ops);
unw_cursor_t* cursor;
void* frame_base;
- mc_snapshot_t snapshot;
+ mc_address_space_t address_space;
mc_object_info_t object_info;
int process_index;
} s_mc_expression_state_t, *mc_expression_state_t;
* @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, int process_index)
+ mc_address_space_t address_space, int process_index)
{
if (!member->location.size) {
return ((char *) base) + member->offset;
memset(&state, 0, sizeof(s_mc_expression_state_t));
state.frame_base = NULL;
state.cursor = NULL;
- state.snapshot = snapshot;
+ state.address_space = address_space;
state.stack_size = 1;
state.stack[0] = (uintptr_t) base;
state.process_index = process_index;
* @return Virtual memory page number of the given address
*/
static inline __attribute__ ((always_inline))
-size_t mc_page_number(void* base, void* address)
+size_t mc_page_number(const void* base, const void* address)
{
xbt_assert(address>=base, "The address is not in the range");
return ((uintptr_t) address - (uintptr_t) base) >> xbt_pagebits;
* @return Offset within the memory page
*/
static inline __attribute__ ((always_inline))
-size_t mc_page_offset(void* address)
+size_t mc_page_offset(const void* address)
{
return ((uintptr_t) address) & (xbt_pagesize-1);
}
* @param page Index of the page
*/
static inline __attribute__ ((always_inline))
-void* mc_page_from_number(void* base, size_t page)
+void* mc_page_from_number(const void* base, size_t page)
{
return (void*) ((char*)base + (page << xbt_pagebits));
}
static inline __attribute__ ((always_inline))
-bool mc_same_page(void* a, void* b)
+bool mc_same_page(const void* a, const void* b)
{
return ((uintptr_t) a >> xbt_pagebits) == ((uintptr_t) b >> xbt_pagebits);
}
- /* Copyright (c) 2007-2014. The SimGrid Team.
+/* Copyright (c) 2007-2014. The SimGrid Team.
* All rights reserved. */
/* This program is free software; you can redistribute it and/or modify it
// Not used:
char* get_type_description(mc_object_info_t info, char *type_name);
-void* mc_member_resolve(const void* base, dw_type_t type, dw_type_t member, mc_snapshot_t snapshot, int process_index);
+void* mc_member_resolve(const void* base, dw_type_t type, dw_type_t member, mc_address_space_t snapshot, int process_index);
struct s_dw_variable{
Dwarf_Off dwarf_offset; /* Global offset of the field. */
- move the segments in shared memory (this will break `fork` however).
*/
page_data = temp;
- MC_process_read(process, temp, page, xbt_pagesize);
+ MC_process_read(process, MC_ADDRESS_SPACE_READ_FLAGS_NONE,
+ temp, page, xbt_pagesize, MC_PROCESS_INDEX_DISABLED);
}
pagenos[i] = mc_model_checker->pages->store_page(page_data);
}
#include "mc_process.h"
#include "mc_object_info.h"
+#include "mc_address_space.h"
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_process, mc,
"MC process information");
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
+};
void MC_process_init(mc_process_t process, pid_t pid)
{
+ process->address_space.address_space_class = &mc_process_class;
process->process_flags = MC_PROCESS_NO_FLAG;
process->pid = pid;
if (pid==getpid())
xbt_die("No heap information in the target process");
if(!std_heap_var->address)
xbt_die("No constant address for this variable");
- MC_process_read(process, &process->heap_address,
- std_heap_var->address, sizeof(struct mdesc*));
+ MC_process_read(process, MC_ADDRESS_SPACE_READ_FLAGS_NONE,
+ &process->heap_address, std_heap_var->address, sizeof(struct mdesc*),
+ MC_PROCESS_INDEX_DISABLED);
}
void MC_process_clear(mc_process_t process)
{
+ process->address_space.address_space_class = NULL;
process->process_flags = MC_PROCESS_NO_FLAG;
process->pid = 0;
process->heap = malloc(sizeof(struct mdesc));
mmalloc_set_current_heap(oldheap);
}
- MC_process_read(process, process->heap,
- process->heap_address, sizeof(struct mdesc));
+ MC_process_read(process, MC_ADDRESS_SPACE_READ_FLAGS_NONE,
+ process->heap, process->heap_address, sizeof(struct mdesc),
+ MC_PROCESS_INDEX_DISABLED
+ );
}
void MC_process_refresh_malloc_info(mc_process_t process)
malloc_info_bytesize);
mmalloc_set_current_heap(oldheap);
- MC_process_read(process, process->heap_info,
- process->heap->heapinfo, malloc_info_bytesize);
+ MC_process_read(process, MC_ADDRESS_SPACE_READ_FLAGS_NONE,
+ process->heap_info,
+ process->heap->heapinfo, malloc_info_bytesize,
+ MC_PROCESS_INDEX_DISABLED);
}
#define SO_RE "\\.so[\\.0-9]*$"
return real_count;
}
-void MC_process_read(mc_process_t process, void* local, const void* remote, size_t len)
+const void* MC_process_read(mc_process_t process, e_adress_space_read_flags_t flags,
+ void* local, const void* remote, size_t len,
+ int process_index)
{
+ if (process_index != MC_PROCESS_INDEX_DISABLED)
+ xbt_die("Not implemented yet");
+
if (MC_process_is_self(process)) {
- memcpy(local, remote, len);
+ if (flags & MC_ADDRESS_SPACE_READ_FLAGS_LAZY)
+ return remote;
+ else {
+ memcpy(local, remote, len);
+ return local;
+ }
} else {
if (pread_whole(process->memory_file, local, len, (off_t) remote) < 0)
xbt_die("Read from process %lli failed", (long long) process->pid);
+ return local;
}
}
#include "mc_forward.h"
#include "mc_mmalloc.h" // std_heap
#include "mc_memory_map.h"
+#include "mc_address_space.h"
SG_BEGIN_DECL()
/** Representation of a process
*/
struct s_mc_process {
+ s_mc_address_space_t address_space;
e_mc_process_flags_t process_flags;
pid_t pid;
memory_map_t memory_map;
* @param remote target process memory address (source)
* @param len data size
*/
-void MC_process_read(mc_process_t process, void* local, const void* remote, size_t len);
+const void* MC_process_read(mc_process_t process,
+ e_adress_space_read_flags_t flags,
+ void* local, const void* remote, size_t len,
+ int process_index);
/** Write data to a process memory
*
* @param Snapshot region in the snapshot this pointer belongs to
* (or NULL if it does not belong to any snapshot region)
* */
-mc_mem_region_t mc_get_snapshot_region(void* addr, mc_snapshot_t snapshot, int process_index)
+mc_mem_region_t mc_get_snapshot_region(const void* addr, mc_snapshot_t snapshot, int process_index)
{
size_t n = snapshot->snapshot_regions_count;
for (size_t i = 0; i != n; ++i) {
if (region->storage_type == MC_REGION_STORAGE_TYPE_PRIVATIZED) {
#ifdef HAVE_SMPI
+ // Use the current process index of the snapshot:
+ if (process_index == MC_PROCESS_INDEX_DISABLED) {
+ process_index = snapshot->privatization_index;
+ }
if (process_index < 0) {
xbt_die("Missing process index");
}
* @param size Size of the data to read in bytes
* @return Pointer where the data is located (target buffer of original location)
*/
-void* mc_snapshot_read_fragmented(void* addr, mc_mem_region_t region, void* target, size_t size)
+const void* MC_region_read_fragmented(mc_mem_region_t region, void* target, const void* addr, size_t size)
{
// Last byte of the memory area:
void* end = (char*) addr + size - 1;
* @param size Size of the data to read in bytes
* @return Pointer where the data is located (target buffer or original location)
*/
-void* mc_snapshot_read(void* addr, mc_snapshot_t snapshot, int process_index, void* target, size_t size)
+const void* MC_snapshot_read(
+ mc_snapshot_t snapshot, e_adress_space_read_flags_t flags,
+ void* target, const void* addr, size_t size, int process_index)
{
- if (snapshot) {
- mc_mem_region_t region = mc_get_snapshot_region(addr, snapshot, process_index);
- return mc_snapshot_read_region(addr, region, target, size);
- } else {
- return addr;
- }
+ mc_mem_region_t region = mc_get_snapshot_region(addr, snapshot, process_index);
+ if (region)
+ return MC_region_read(region, target, addr, size);
+ else
+ return MC_process_read(snapshot->process, flags, target, addr, size, process_index);
}
/** Compare memory between snapshots (with known regions)
* @param snapshot2 Region of the address in the second snapshot
* @return same as memcmp
* */
-int mc_snapshot_region_memcmp(
- void* addr1, mc_mem_region_t region1,
- void* addr2, mc_mem_region_t region2,
+int MC_snapshot_region_memcmp(
+ const void* addr1, mc_mem_region_t region1,
+ const void* addr2, mc_mem_region_t region2,
size_t size)
{
// Using alloca() for large allocations may trigger stack overflow:
const bool region2_need_buffer = region2==NULL || region2->storage_type==MC_REGION_STORAGE_TYPE_FLAT;
void* buffer1a = region1_need_buffer ? NULL : stack_alloc ? alloca(size) : malloc(size);
void* buffer2a = region2_need_buffer ? NULL : stack_alloc ? alloca(size) : malloc(size);
- void* buffer1 = mc_snapshot_read_region(addr1, region1, buffer1a, size);
- void* buffer2 = mc_snapshot_read_region(addr2, region2, buffer2a, size);
+ const void* buffer1 = MC_region_read(region1, buffer1a, addr1, size);
+ const void* buffer2 = MC_region_read(region2, buffer2a, addr2, size);
int res;
if (buffer1 == buffer2) {
res = 0;
* @param snapshot2 Second snapshot
* @return same as memcmp
* */
-int mc_snapshot_memcmp(
- void* addr1, mc_snapshot_t snapshot1,
- void* addr2, mc_snapshot_t snapshot2, int process_index, size_t size)
+int MC_snapshot_memcmp(
+ const void* addr1, mc_snapshot_t snapshot1,
+ const void* addr2, mc_snapshot_t snapshot2, int process_index, size_t size)
{
mc_mem_region_t region1 = mc_get_snapshot_region(addr1, snapshot1, process_index);
mc_mem_region_t region2 = mc_get_snapshot_region(addr2, snapshot2, process_index);
- return mc_snapshot_region_memcmp(addr1, region1, addr2, region2, size);
+ return MC_snapshot_region_memcmp(addr1, region1, addr2, region2, size);
}
#ifdef SIMGRID_TEST
xbt_assert(source!=MAP_FAILED, "Could not allocate destination memory");
xbt_test_add("Reading whole region data for %i page(s)", n);
- void* read = mc_snapshot_read_region(source, region, destination, byte_size);
- xbt_test_assert(!memcmp(source, read, byte_size), "Mismatch in mc_snapshot_read_region()");
+ const void* read = MC_region_read(region, source, destination, byte_size);
+ xbt_test_assert(!memcmp(source, read, byte_size), "Mismatch in MC_region_read()");
xbt_test_add("Reading parts of region data for %i page(s)", n);
for(int j=0; j!=100; ++j) {
size_t offset = rand() % byte_size;
size_t size = rand() % (byte_size - offset);
- void* read = mc_snapshot_read_region((char*) source+offset, region, destination, size);
+ const void* read = MC_region_read(region, destination, (const char*) source+offset, size);
xbt_test_assert(!memcmp((char*) source+offset, read, size),
- "Mismatch in mc_snapshot_read_region()");
+ "Mismatch in MC_region_read()");
}
xbt_test_add("Compare whole region data for %i page(s)", n);
- xbt_test_assert(!mc_snapshot_region_memcmp(source, NULL, source, region, byte_size),
- "Mismatch in mc_snapshot_region_memcmp() for the whole region");
- xbt_test_assert(mc_snapshot_region_memcmp(source, region0, source, region, byte_size),
- "Unexpected match in mc_snapshot_region_memcmp() with previous snapshot");
+ xbt_test_assert(!MC_snapshot_region_memcmp(source, NULL, source, region, byte_size),
+ "Mismatch in MC_snapshot_region_memcmp() for the whole region");
+ xbt_test_assert(MC_snapshot_region_memcmp(source, region0, source, region, byte_size),
+ "Unexpected match in MC_snapshot_region_memcmp() with previous snapshot");
xbt_test_add("Compare parts of region data for %i page(s) with current value", n);
for(int j=0; j!=100; ++j) {
size_t offset = rand() % byte_size;
size_t size = rand() % (byte_size - offset);
- xbt_test_assert(!mc_snapshot_region_memcmp((char*) source+offset, NULL, (char*) source+offset, region, size),
- "Mismatch in mc_snapshot_region_memcmp()");
+ xbt_test_assert(!MC_snapshot_region_memcmp((char*) source+offset, NULL, (char*) source+offset, region, size),
+ "Mismatch in MC_snapshot_region_memcmp()");
}
xbt_test_add("Compare parts of region data for %i page(s) with itself", n);
for(int j=0; j!=100; ++j) {
size_t offset = rand() % byte_size;
size_t size = rand() % (byte_size - offset);
- xbt_test_assert(!mc_snapshot_region_memcmp((char*) source+offset, region, (char*) source+offset, region, size),
- "Mismatch in mc_snapshot_region_memcmp()");
+ xbt_test_assert(!MC_snapshot_region_memcmp((char*) source+offset, region, (char*) source+offset, region, size),
+ "Mismatch in MC_snapshot_region_memcmp()");
}
if (n==1) {
xbt_test_add("Read pointer for %i page(s)", n);
memcpy(source, &mc_model_checker, sizeof(void*));
mc_mem_region_t region2 = mc_region_new_sparse(MC_REGION_TYPE_UNKNOWN, source, source, byte_size, NULL);
- xbt_test_assert(mc_snapshot_read_pointer_region(source, region2) == mc_model_checker,
- "Mismtach in mc_snapshot_read_pointer_region()");
+ xbt_test_assert(MC_region_read_pointer(region2, source) == mc_model_checker,
+ "Mismtach in MC_region_read_pointer()");
MC_region_destroy(region2);
}
#include "mc_model_checker.h"
#include "mc_page_store.h"
#include "mc_mmalloc.h"
+#include "mc_address_space.h"
SG_BEGIN_DECL()
void mc_region_restore_sparse(mc_process_t process, mc_mem_region_t reg, mc_mem_region_t ref_reg);
static inline __attribute__ ((always_inline))
-bool mc_region_contain(mc_mem_region_t region, void* p)
+bool mc_region_contain(mc_mem_region_t region, const void* p)
{
return p >= region->start_addr &&
p < (void*)((char*) region->start_addr + region->size);
return (char*) snapshot_page + mc_page_offset((void*) addr);
}
-mc_mem_region_t mc_get_snapshot_region(void* addr, mc_snapshot_t snapshot, int process_index);
+mc_mem_region_t mc_get_snapshot_region(const void* addr, mc_snapshot_t snapshot, int process_index);
/** \brief Translate a pointer from process address space to snapshot address space
*
int flags;
}s_fd_infos_t, *fd_infos_t;
-struct s_mc_snapshot{
+struct s_mc_snapshot {
+ mc_process_t process;
+ s_mc_address_space_t address_space;
size_t heap_bytes_used;
mc_mem_region_t* snapshot_regions;
size_t snapshot_regions_count;
fd_infos_t *current_fd;
};
-/** @brief Process index used when no process is available
- *
- * The expected behaviour is that if a process index is needed it will fail.
- * */
-#define MC_NO_PROCESS_INDEX -1
-
-/** @brief Process index when any process is suitable
- *
- * We could use a special negative value in the future.
- */
-#define MC_ANY_PROCESS_INDEX 0
-
static inline __attribute__ ((always_inline))
mc_mem_region_t mc_get_region_hinted(void* addr, mc_snapshot_t snapshot, int process_index, mc_mem_region_t region)
{
int process_index;
}s_mc_snapshot_stack_t, *mc_snapshot_stack_t;
-typedef struct s_mc_global_t{
+typedef struct s_mc_global_t {
mc_snapshot_t snapshot;
int raw_mem_set;
int prev_pair;
size_t size;
}s_mc_checkpoint_ignore_region_t, *mc_checkpoint_ignore_region_t;
-static void* mc_snapshot_get_heap_end(mc_snapshot_t snapshot);
+static const void* mc_snapshot_get_heap_end(mc_snapshot_t snapshot);
mc_snapshot_t MC_take_snapshot(int num_state);
void MC_restore_snapshot(mc_snapshot_t);
void* start_addr, size_t page_count, size_t* pagenos,
uint64_t* pagemap, size_t* reference_pagenos);
-void* mc_snapshot_read_fragmented(void* addr, mc_mem_region_t region, void* target, size_t size);
+const void* MC_region_read_fragmented(mc_mem_region_t region, void* target, const void* addr, size_t size);
-void* mc_snapshot_read(void* addr, mc_snapshot_t snapshot, int process_index, void* target, size_t size);
-int mc_snapshot_region_memcmp(
- void* addr1, mc_mem_region_t region1,
- void* addr2, mc_mem_region_t region2, size_t size);
-int mc_snapshot_memcmp(
- void* addr1, mc_snapshot_t snapshot1,
- void* addr2, mc_snapshot_t snapshot2, int process_index, size_t size);
-
-static void* mc_snapshot_read_pointer(void* addr, mc_snapshot_t snapshot, int process_index);
+const void* MC_snapshot_read(mc_snapshot_t snapshot, e_adress_space_read_flags_t flags,
+ void* target, const void* addr, size_t size, int process_index);
+int MC_snapshot_region_memcmp(
+ const void* addr1, mc_mem_region_t region1,
+ const void* addr2, mc_mem_region_t region2, size_t size);
+int MC_snapshot_memcmp(
+ const void* addr1, mc_snapshot_t snapshot1,
+ const void* addr2, mc_snapshot_t snapshot2, int process_index, size_t size);
static inline __attribute__ ((always_inline))
-void* mc_snapshot_read_pointer(void* addr, mc_snapshot_t snapshot, int process_index)
+const void* MC_snapshot_read_pointer(mc_snapshot_t snapshot, const void* addr, int process_index)
{
void* res;
- return *(void**) mc_snapshot_read(addr, snapshot, process_index, &res, sizeof(void*));
+ return *(const void**) MC_snapshot_read(snapshot, MC_ADDRESS_SPACE_READ_FLAGS_LAZY,
+ &res, addr, sizeof(void*), process_index);
}
static inline __attribute__ ((always_inline))
-void* mc_snapshot_get_heap_end(mc_snapshot_t snapshot) {
+const void* mc_snapshot_get_heap_end(mc_snapshot_t snapshot)
+{
if(snapshot==NULL)
xbt_die("snapshot is NULL");
// This is &std_heap->breakval in the target process:
void** addr = &MC_process_get_heap(&mc_model_checker->process)->breakval;
// Read (std_heap->breakval) in the target process (*addr i.e. std_heap->breakval):
- return mc_snapshot_read_pointer(addr, snapshot, MC_ANY_PROCESS_INDEX);
+ return MC_snapshot_read_pointer(snapshot, addr, MC_PROCESS_INDEX_ANY);
}
/** @brief Read memory from a snapshot region
* @return Pointer where the data is located (target buffer of original location)
*/
static inline __attribute__((always_inline))
-void* mc_snapshot_read_region(void* addr, mc_mem_region_t region, void* target, size_t size)
+const void* MC_region_read(mc_mem_region_t region, void* target, const void* addr, size_t size)
{
if (region==NULL)
+ // Should be deprecated:
return addr;
uintptr_t offset = (char*) addr - (char*) region->start_addr;
{
// Last byte of the region:
void* end = (char*) addr + size - 1;
- if( mc_same_page(addr, end) ) {
+ if (mc_same_page(addr, end) ) {
// The memory is contained in a single page:
return mc_translate_address_region((uintptr_t) addr, region);
} else {
// The memory spans several pages:
- return mc_snapshot_read_fragmented(addr, region, target, size);
+ return MC_region_read_fragmented(region, target, addr, size);
}
}
}
static inline __attribute__ ((always_inline))
-void* mc_snapshot_read_pointer_region(void* addr, mc_mem_region_t region)
+void* MC_region_read_pointer(mc_mem_region_t region, const void* addr)
{
void* res;
- return *(void**) mc_snapshot_read_region(addr, region, &res, sizeof(void*));
+ return *(void**) MC_region_read(region, &res, addr, sizeof(void*));
}
SG_END_DECL()