/* 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. */
+#define _FILE_OFFSET_BITS 64
+
#include <assert.h>
#include <stddef.h>
#include <stdbool.h>
#include "mc_process.h"
#include "mc_object_info.h"
-#include "mc_address_space.h"
+#include "AddressSpace.hpp"
#include "mc_unw.h"
#include "mc_snapshot.h"
#include "mc_ignore.h"
#include "mc_smx.h"
#include "mc_server.h"
+using simgrid::mc::remote;
+
extern "C" {
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);
+// ***** Helper stuff
-// ***** Destructor callbacks
+#define SO_RE "\\.so[\\.0-9]*$"
+#define VERSION_RE "-[\\.0-9-]*$"
-// ***** mc_address_space methods for mc_process
+static const char *const FILTERED_LIBS[] = {
+ "ld",
+ "libbz2",
+ "libboost_context",
+ "libc",
+ "libc++",
+ "libcdt",
+ "libcgraph",
+ "libdl",
+ "libdw",
+ "libelf",
+ "libgcc_s",
+ "liblua5.1",
+ "liblzma",
+ "libm",
+ "libpthread",
+ "librt",
+ "libstdc++",
+ "libunwind",
+ "libunwind-x86_64",
+ "libunwind-x86",
+ "libunwind-ptrace",
+ "libz"
+};
-static mc_process_t MC_process_get_process(mc_process_t p) {
- return p;
+static bool MC_is_simgrid_lib(const char* libname)
+{
+ return !strcmp(libname, "libsimgrid");
}
-static const s_mc_address_space_class_t mc_process_class = {
- .read = (mc_address_space_class_read_callback_t) &MC_process_read,
- .get_process = (mc_address_space_class_get_process_callback_t) MC_process_get_process
+static bool MC_is_filtered_lib(const char* libname)
+{
+ for (const char* filtered_lib : FILTERED_LIBS)
+ if (strcmp(libname, filtered_lib)==0)
+ return true;
+ return false;
+}
+
+struct s_mc_memory_map_re {
+ regex_t so_re;
+ regex_t version_re;
};
-bool MC_is_process(mc_address_space_t p)
+static char* MC_get_lib_name(const char* pathname, struct s_mc_memory_map_re* res)
+{
+ const char* map_basename = basename((char*) pathname);
+
+ regmatch_t match;
+ if(regexec(&res->so_re, map_basename, 1, &match, 0))
+ return NULL;
+
+ char* libname = strndup(map_basename, match.rm_so);
+
+ // Strip the version suffix:
+ if(libname && !regexec(&res->version_re, libname, 1, &match, 0)) {
+ char* temp = libname;
+ libname = strndup(temp, match.rm_so);
+ free(temp);
+ }
+
+ return libname;
+}
+
+static ssize_t pread_whole(int fd, void *buf, size_t count, std::uint64_t offset)
+{
+ char* buffer = (char*) buf;
+ ssize_t real_count = count;
+ while (count) {
+ ssize_t res = pread(fd, buffer, count, (std::int64_t) offset);
+ if (res > 0) {
+ count -= res;
+ buffer += res;
+ offset += res;
+ } else if (res==0) {
+ return -1;
+ } else if (errno != EINTR) {
+ return -1;
+ }
+ }
+ return real_count;
+}
+
+static ssize_t pwrite_whole(int fd, const void *buf, size_t count, off_t offset)
+{
+ const char* buffer = (const char*) buf;
+ ssize_t real_count = count;
+ while (count) {
+ ssize_t res = pwrite(fd, buffer, count, offset);
+ if (res > 0) {
+ count -= res;
+ buffer += res;
+ offset += res;
+ } else if (res==0) {
+ return -1;
+ } else if (errno != EINTR) {
+ return -1;
+ }
+ }
+ return real_count;
+}
+
+static pthread_once_t zero_buffer_flag = PTHREAD_ONCE_INIT;
+static const void* zero_buffer;
+static const size_t zero_buffer_size = 10 * 4096;
+
+static void MC_zero_buffer_init(void)
{
- return p->address_space_class == &mc_process_class;
+ int fd = open("/dev/zero", O_RDONLY);
+ if (fd<0)
+ xbt_die("Could not open /dev/zero");
+ zero_buffer = mmap(NULL, zero_buffer_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (zero_buffer == MAP_FAILED)
+ xbt_die("Could not map the zero buffer");
+ close(fd);
+}
+
}
-// ***** mc_process
+namespace simgrid {
+namespace mc {
-void MC_process_init(mc_process_t process, pid_t pid, int sockfd)
+int open_vm(pid_t pid, int flags)
{
- process->address_space.address_space_class = &mc_process_class;
+ const size_t buffer_size = 30;
+ char buffer[buffer_size];
+ int res = snprintf(buffer, buffer_size, "/proc/%lli/mem", (long long) pid);
+ if (res < 0 || (size_t) res >= buffer_size) {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ return open(buffer, flags);
+}
+
+
+}
+}
+
+// ***** Process
+
+namespace simgrid {
+namespace mc {
+
+Process::Process(pid_t pid, int sockfd)
+{
+ Process* process = this;
+
process->process_flags = MC_PROCESS_NO_FLAG;
- process->socket = sockfd;
- process->pid = pid;
+ 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->running_ = true;
+ process->status_ = 0;
+ process->memory_map_ = get_memory_map(pid);
process->cache_flags = MC_PROCESS_CACHE_FLAG_NONE;
process->heap = NULL;
process->heap_info = NULL;
- MC_process_init_memory_map_info(process);
- MC_process_open_memory_file(process);
+ process->init_memory_map_info();
+
+ // Open the memory file
+ if (process->is_self())
+ process->memory_file = -1;
+ else {
+ int fd = open_vm(process->pid_, O_RDWR);
+ if (fd<0)
+ xbt_die("Could not open file for process virtual address space");
+ process->memory_file = fd;
+ }
// Read std_heap (is a struct mdesc*):
- dw_variable_t std_heap_var = MC_process_find_variable_by_name(process,
- "__mmalloc_default_mdp");
+ dw_variable_t std_heap_var = process->find_variable("__mmalloc_default_mdp");
if (!std_heap_var)
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, MC_ADDRESS_SPACE_READ_FLAGS_NONE,
- &process->heap_address, std_heap_var->address, sizeof(struct mdesc*),
- MC_PROCESS_INDEX_DISABLED);
+ process->read_bytes(&process->heap_address, sizeof(struct mdesc*),
+ remote(std_heap_var->address),
+ simgrid::mc::ProcessIndexDisabled);
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;
}
}
-void MC_process_clear(mc_process_t process)
+Process::~Process()
{
- process->address_space.address_space_class = NULL;
- process->process_flags = MC_PROCESS_NO_FLAG;
- process->pid = 0;
+ Process* process = this;
- MC_free_memory_map(process->memory_map);
- process->memory_map = NULL;
+ if (this->socket_ >= 0 && close(this->socket_) < 0)
+ xbt_die("Could not close communication socket");
- process->maestro_stack_start = NULL;
- process->maestro_stack_end = NULL;
+ process->process_flags = MC_PROCESS_NO_FLAG;
+ process->pid_ = 0;
- xbt_dynar_free(&process->checkpoint_ignore);
+ process->maestro_stack_start_ = nullptr;
+ process->maestro_stack_end_ = nullptr;
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]);
- }
- free(process->object_infos);
- process->object_infos = NULL;
- process->object_infos_size = 0;
if (process->memory_file >= 0) {
close(process->memory_file);
}
process->heap_info = NULL;
}
-void MC_process_refresh_heap(mc_process_t process)
+/** Refresh the information about the process
+ *
+ * Do not use direclty, this is used by the getters when appropriate
+ * in order to have fresh data.
+ */
+void Process::refresh_heap()
{
xbt_assert(mc_mode == MC_MODE_SERVER);
- xbt_assert(!MC_process_is_self(process));
+ xbt_assert(!this->is_self());
// Read/dereference/refresh the std_heap pointer:
- if (!process->heap) {
- process->heap = (struct mdesc*) malloc(sizeof(struct mdesc));
+ if (!this->heap) {
+ this->heap = (struct mdesc*) malloc(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
- );
- process->cache_flags |= MC_PROCESS_CACHE_FLAG_HEAP;
+ this->read_bytes(this->heap, sizeof(struct mdesc), remote(this->heap_address),
+ simgrid::mc::ProcessIndexDisabled);
+ this->cache_flags |= MC_PROCESS_CACHE_FLAG_HEAP;
}
-void MC_process_refresh_malloc_info(mc_process_t process)
+/** Refresh the information about the process
+ *
+ * Do not use direclty, this is used by the getters when appropriate
+ * in order to have fresh data.
+ * */
+void Process::refresh_malloc_info()
{
xbt_assert(mc_mode == MC_MODE_SERVER);
- xbt_assert(!MC_process_is_self(process));
- if (!(process->cache_flags & MC_PROCESS_CACHE_FLAG_HEAP))
- MC_process_refresh_heap(process);
+ xbt_assert(!this->is_self());
+ if (!(this->cache_flags & MC_PROCESS_CACHE_FLAG_HEAP))
+ this->refresh_heap();
// Refresh process->heapinfo:
size_t malloc_info_bytesize =
- (process->heap->heaplimit + 1) * sizeof(malloc_info);
- process->heap_info = (malloc_info*) realloc(process->heap_info, 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);
- process->cache_flags |= MC_PROCESS_CACHE_FLAG_MALLOC_INFO;
-}
-
-#define SO_RE "\\.so[\\.0-9]*$"
-#define VERSION_RE "-[\\.0-9]*$"
-
-const char* FILTERED_LIBS[] = {
- "libstdc++",
- "libc++",
- "libm",
- "libgcc_s",
- "libpthread",
- "libunwind",
- "libunwind-x86_64",
- "libunwind-x86",
- "libunwind-ptrace",
- "libdw",
- "libdl",
- "librt",
- "liblzma",
- "libelf",
- "libbz2",
- "libz",
- "libelf",
- "libc",
- "ld"
-};
-
-static bool MC_is_simgrid_lib(const char* libname)
-{
- return !strcmp(libname, "libsimgrid");
-}
-
-static bool MC_is_filtered_lib(const char* libname)
-{
- const size_t n = sizeof(FILTERED_LIBS) / sizeof(const char*);
- size_t i;
- for (i=0; i!=n; ++i)
- if (strcmp(libname, FILTERED_LIBS[i])==0)
- return true;
- return false;
-}
-
-struct s_mc_memory_map_re {
- regex_t so_re;
- regex_t version_re;
-};
-
-static char* MC_get_lib_name(const char* pathname, struct s_mc_memory_map_re* res) {
- const char* map_basename = basename((char*) pathname);
-
- regmatch_t match;
- if(regexec(&res->so_re, map_basename, 1, &match, 0))
- return NULL;
-
- char* libname = strndup(map_basename, match.rm_so);
-
- // Strip the version suffix:
- if(libname && !regexec(&res->version_re, libname, 1, &match, 0)) {
- char* temp = libname;
- libname = strndup(temp, match.rm_so);
- free(temp);
- }
-
- return libname;
+ (this->heap->heaplimit + 1) * sizeof(malloc_info);
+ this->heap_info = (malloc_info*) realloc(this->heap_info, malloc_info_bytesize);
+ this->read_bytes(this->heap_info, malloc_info_bytesize,
+ remote(this->heap->heapinfo), simgrid::mc::ProcessIndexDisabled);
+ this->cache_flags |= MC_PROCESS_CACHE_FLAG_MALLOC_INFO;
}
/** @brief Finds the range of the different memory segments and binary paths */
-static void MC_process_init_memory_map_info(mc_process_t process)
+void Process::init_memory_map_info()
{
XBT_DEBUG("Get debug information ...");
- process->maestro_stack_start = NULL;
- process->maestro_stack_end = NULL;
- process->object_infos = NULL;
- process->object_infos_size = 0;
- process->binary_info = NULL;
- process->libsimgrid_info = NULL;
+ this->maestro_stack_start_ = nullptr;
+ this->maestro_stack_end_ = nullptr;
+ this->object_infos.resize(0);
+ this->binary_info = NULL;
+ this->libsimgrid_info = NULL;
struct s_mc_memory_map_re res;
if(regcomp(&res.so_re, SO_RE, 0) || regcomp(&res.version_re, VERSION_RE, 0))
xbt_die(".so regexp did not compile");
- memory_map_t maps = process->memory_map;
+ std::vector<simgrid::mc::VmMap> const& maps = this->memory_map_;
const char* current_name = NULL;
- for (ssize_t i=0; i < maps->mapsize; i++) {
- map_region_t reg = &(maps->regions[i]);
- const char* pathname = maps->regions[i].pathname;
+ this->object_infos.resize(0);
+
+ for (size_t i=0; i < maps.size(); i++) {
+ simgrid::mc::VmMap const& reg = maps[i];
+ const char* pathname = maps[i].pathname.c_str();
// Nothing to do
- if (maps->regions[i].pathname == NULL) {
+ if (maps[i].pathname.empty()) {
current_name = NULL;
continue;
}
// [stack], [vvar], [vsyscall], [vdso] ...
if (pathname[0] == '[') {
- if ((reg->prot & PROT_WRITE) && !memcmp(pathname, "[stack]", 7)) {
- process->maestro_stack_start = reg->start_addr;
- process->maestro_stack_end = reg->end_addr;
+ if ((reg.prot & PROT_WRITE) && !memcmp(pathname, "[stack]", 7)) {
+ this->maestro_stack_start_ = remote(reg.start_addr);
+ this->maestro_stack_end_ = remote(reg.end_addr);
}
current_name = NULL;
continue;
continue;
current_name = pathname;
- if (!(reg->prot & PROT_READ) && (reg->prot & PROT_EXEC))
+ if (!(reg.prot & PROT_READ) && (reg.prot & PROT_EXEC))
continue;
const bool is_executable = !i;
}
}
- mc_object_info_t info =
- MC_find_object_info(process->memory_map, pathname, is_executable);
- process->object_infos = (mc_object_info_t*) realloc(process->object_infos,
- (process->object_infos_size+1) * sizeof(mc_object_info_t*));
- process->object_infos[process->object_infos_size] = info;
- process->object_infos_size++;
+ std::shared_ptr<s_mc_object_info_t> info =
+ MC_find_object_info(this->memory_map_, pathname, is_executable);
+ this->object_infos.push_back(info);
if (is_executable)
- process->binary_info = info;
+ this->binary_info = info;
else if (libname && MC_is_simgrid_lib(libname))
- process->libsimgrid_info = info;
+ this->libsimgrid_info = info;
free(libname);
}
regfree(&res.so_re);
regfree(&res.version_re);
- // Resolve time (including accress differents objects):
- for (size_t i=0; i!=process->object_infos_size; ++i)
- MC_post_process_object_info(process, process->object_infos[i]);
+ // Resolve time (including accross differents objects):
+ for (auto const& object_info : this->object_infos)
+ MC_post_process_object_info(this, object_info.get());
- 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_assert(this->maestro_stack_start_, "Did not find maestro_stack_start");
+ xbt_assert(this->maestro_stack_end_, "Did not find maestro_stack_end");
XBT_DEBUG("Get debug information done !");
}
-mc_object_info_t MC_process_find_object_info(mc_process_t process, const void *addr)
+std::shared_ptr<s_mc_object_info_t> Process::find_object_info(remote_ptr<void> addr) const
{
- size_t i;
- for (i = 0; i != process->object_infos_size; ++i) {
- if (addr >= (void *) process->object_infos[i]->start
- && addr <= (void *) process->object_infos[i]->end) {
- return process->object_infos[i];
+ for (auto const& object_info : this->object_infos) {
+ if (addr.address() >= (std::uint64_t)object_info->start
+ && addr.address() <= (std::uint64_t)object_info->end) {
+ return object_info;
}
}
return NULL;
}
-mc_object_info_t MC_process_find_object_info_exec(mc_process_t process, const void *addr)
+std::shared_ptr<s_mc_object_info_t> Process::find_object_info_exec(remote_ptr<void> addr) const
{
- size_t i;
- for (i = 0; i != process->object_infos_size; ++i) {
- if (addr >= (void *) process->object_infos[i]->start_exec
- && addr <= (void *) process->object_infos[i]->end_exec) {
- return process->object_infos[i];
+ for (std::shared_ptr<s_mc_object_info> const& info : this->object_infos) {
+ if (addr.address() >= (std::uint64_t) info->start_exec
+ && addr.address() <= (std::uint64_t) info->end_exec) {
+ return info;
}
}
- return NULL;
+ return nullptr;
}
-mc_object_info_t MC_process_find_object_info_rw(mc_process_t process, const void *addr)
+std::shared_ptr<s_mc_object_info_t> Process::find_object_info_rw(remote_ptr<void> addr) const
{
- size_t i;
- for (i = 0; i != process->object_infos_size; ++i) {
- if (addr >= (void *) process->object_infos[i]->start_rw
- && addr <= (void *) process->object_infos[i]->end_rw) {
- return process->object_infos[i];
+ for (std::shared_ptr<s_mc_object_info> const& info : this->object_infos) {
+ if (addr.address() >= (std::uint64_t)info->start_rw
+ && addr.address() <= (std::uint64_t)info->end_rw) {
+ return info;
}
}
- return NULL;
+ return nullptr;
}
-// Functions, variables…
-
-dw_frame_t MC_process_find_function(mc_process_t process, const void *ip)
+dw_frame_t Process::find_function(remote_ptr<void> ip) const
{
- mc_object_info_t info = MC_process_find_object_info_exec(process, ip);
- if (info == NULL)
- return NULL;
+ std::shared_ptr<s_mc_object_info_t> info = this->find_object_info_exec(ip);
+ if (!info)
+ return nullptr;
else
- return MC_file_object_info_find_function(info, ip);
+ return MC_file_object_info_find_function(info.get(), (void*) ip.address());
}
-dw_variable_t MC_process_find_variable_by_name(mc_process_t process, const char* name)
+/** Find (one occurence of) the named variable definition
+ */
+dw_variable_t Process::find_variable(const char* name) const
{
- 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 (this->binary_info) {
+ std::shared_ptr<s_mc_object_info_t> const& info = this->binary_info;
+ dw_variable_t var = MC_file_object_info_find_variable_by_name(info.get(), 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);
+ for (std::shared_ptr<s_mc_object_info_t> const& info : this->object_infos) {
+ dw_variable_t var = MC_file_object_info_find_variable_by_name(info.get(), name);
if (var)
return var;
}
return NULL;
}
-void MC_process_read_variable(mc_process_t process, const char* name, void* target, size_t size)
+void Process::read_variable(const char* name, void* target, size_t size) const
{
- dw_variable_t var = MC_process_find_variable_by_name(process, name);
+ dw_variable_t var = this->find_variable(name);
if (!var->address)
xbt_die("No simple location for this variable");
if (!var->type->full_type)
if ((size_t) 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_ADDRESS_SPACE_READ_FLAGS_NONE, target, var->address, size,
- MC_PROCESS_INDEX_ANY);
+ this->read_bytes(target, size, remote(var->address));
}
-char* MC_process_read_string(mc_process_t process, void* address)
+char* Process::read_string(remote_ptr<void> address) const
{
if (!address)
return NULL;
- if (MC_process_is_self(process))
- return strdup((char*) address);
+ if (this->is_self())
+ return xbt_strdup((char*) address.address());
off_t len = 128;
char* res = (char*) malloc(len);
off_t off = 0;
while (1) {
- ssize_t c = pread(process->memory_file, res + off, len - off, (off_t) address + off);
+ ssize_t c = pread(this->memory_file, res + off, len - off, (off_t) address.address() + off);
if (c == -1) {
if (errno == EINTR)
continue;
}
}
-// ***** Memory access
-
-int MC_process_vm_open(pid_t pid, int flags)
-{
- const size_t buffer_size = 30;
- char buffer[buffer_size];
- int res = snprintf(buffer, buffer_size, "/proc/%lli/mem", (long long) pid);
- if (res < 0 || (size_t) res >= buffer_size) {
- errno = ENAMETOOLONG;
- return -1;
- }
- return open(buffer, flags);
-}
-
-static void MC_process_open_memory_file(mc_process_t process)
+const void *Process::read_bytes(void* buffer, std::size_t size,
+ remote_ptr<void> address, int process_index,
+ AddressSpace::ReadMode mode) const
{
- if (MC_process_is_self(process) || process->memory_file >= 0)
- return;
-
- int fd = MC_process_vm_open(process->pid, O_RDWR);
- if (fd<0)
- xbt_die("Could not open file for process virtual address space");
- process->memory_file = fd;
-}
-
-static ssize_t pread_whole(int fd, void *buf, size_t count, off_t offset)
-{
- char* buffer = (char*) buf;
- ssize_t real_count = count;
- while (count) {
- ssize_t res = pread(fd, buffer, count, offset);
- if (res > 0) {
- count -= res;
- buffer += res;
- offset += res;
- } else if (res==0) {
- return -1;
- } else if (errno != EINTR) {
- return -1;
- }
- }
- return real_count;
-}
-
-static ssize_t pwrite_whole(int fd, const void *buf, size_t count, off_t offset)
-{
- const char* buffer = (const char*) buf;
- ssize_t real_count = count;
- while (count) {
- ssize_t res = pwrite(fd, buffer, count, offset);
- if (res > 0) {
- count -= res;
- buffer += res;
- offset += res;
- } else if (res==0) {
- return -1;
- } else if (errno != EINTR) {
- return -1;
- }
- }
- return real_count;
-}
-
-const void* MC_process_read(mc_process_t process, adress_space_read_flags_t flags,
- void* local, const void* remote, size_t len,
- int process_index)
-{
- if (process_index != MC_PROCESS_INDEX_DISABLED) {
- mc_object_info_t info = MC_process_find_object_info_rw(process, remote);
+ if (process_index != simgrid::mc::ProcessIndexDisabled) {
+ std::shared_ptr<s_mc_object_info_t> const& info =
+ this->find_object_info_rw((void*)address.address());
// Segment overlap is not handled.
- if (MC_object_info_is_privatized(info)) {
+ if (MC_object_info_is_privatized(info.get())) {
if (process_index < 0)
xbt_die("Missing process index");
+ if (process_index >= (int) MC_smpi_process_count())
+ xbt_die("Invalid process index");
+
+ // Read smpi_privatisation_regions from MCed:
+ smpi_privatisation_region_t remote_smpi_privatisation_regions =
+ mc_model_checker->process().read_variable<smpi_privatisation_region_t>(
+ "smpi_privatisation_regions");
+
+ s_smpi_privatisation_region_t privatisation_region =
+ mc_model_checker->process().read<s_smpi_privatisation_region_t>(
+ remote(remote_smpi_privatisation_regions + process_index));
+
// Address translation in the privaization segment:
- size_t offset = (const char*) remote - info->start_rw;
- remote = (const char*) remote - offset;
+ size_t offset = address.address() - (std::uint64_t)info->start_rw;
+ address = remote((char*)privatisation_region.address + offset);
}
}
- if (MC_process_is_self(process)) {
- if (flags & MC_ADDRESS_SPACE_READ_FLAGS_LAZY)
- return remote;
+ if (this->is_self()) {
+ if (mode == simgrid::mc::AddressSpace::Lazy)
+ return (void*)address.address();
else {
- memcpy(local, remote, len);
- return local;
+ memcpy(buffer, (void*)address.address(), size);
+ return buffer;
}
} 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;
+ if (pread_whole(this->memory_file, buffer, size, address.address()) < 0)
+ xbt_die("Read from process %lli failed", (long long) this->pid_);
+ return buffer;
}
}
-const void* MC_process_read_simple(mc_process_t process,
- void* local, const void* remote, size_t len)
-{
- adress_space_read_flags_t flags = MC_ADDRESS_SPACE_READ_FLAGS_NONE;
- 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, size_t len)
+/** Write data to a process memory
+ *
+ * @param process the process
+ * @param local local memory address (source)
+ * @param remote target process memory address (target)
+ * @param len data size
+ */
+void Process::write_bytes(const void* buffer, size_t len, remote_ptr<void> address)
{
- s_xbt_dynar_t d;
- MC_process_read_simple(process, &d, remote_dynar, sizeof(d));
- if (i >= d.used)
- xbt_die("Out of bound index %zi/%zi", i, d.used);
- if (len != d.elmsize)
- xbt_die("Bad size in MC_process_read_dynar_element");
- MC_process_read_simple(process, local, xbt_dynar_get_ptr(&d, i), len);
- return local;
+ if (this->is_self()) {
+ memcpy((void*)address.address(), buffer, len);
+ } else {
+ if (pwrite_whole(this->memory_file, buffer, len, address.address()) < 0)
+ xbt_die("Write to process %lli failed", (long long) this->pid_);
+ }
}
-void MC_process_write(mc_process_t process, const void* local, void* remote, size_t len)
+void Process::clear_bytes(remote_ptr<void> address, size_t len)
{
- if (MC_process_is_self(process)) {
- memcpy(remote, local, len);
+ if (this->is_self()) {
+ memset((void*)address.address(), 0, len);
} else {
- if (pwrite_whole(process->memory_file, local, len, (off_t) remote) < 0)
- xbt_die("Write to process %lli failed", (long long) process->pid);
+ pthread_once(&zero_buffer_flag, MC_zero_buffer_init);
+ while (len) {
+ size_t s = len > zero_buffer_size ? zero_buffer_size : len;
+ this->write_bytes(zero_buffer, s, address);
+ address = remote((char*) address.address() + s);
+ len -= s;
+ }
}
}
-unsigned long MC_process_read_dynar_length(mc_process_t process, const void* remote_dynar)
+void Process::ignore_region(std::uint64_t addr, std::size_t size)
{
- if (!remote_dynar)
- return 0;
- unsigned long res;
- MC_process_read_simple(process, &res,
- &((xbt_dynar_t)remote_dynar)->used, sizeof(res));
- return res;
-}
+ IgnoredRegion region;
+ region.addr = addr;
+ region.size = size;
-static pthread_once_t zero_buffer_flag = PTHREAD_ONCE_INIT;
-static const void* zero_buffer;
-static const int zero_buffer_size = 10 * 4096;
+ if (ignored_regions_.empty()) {
+ ignored_regions_.push_back(region);
+ return;
+ }
-static void MC_zero_buffer_init(void)
-{
- int fd = open("/dev/zero", O_RDONLY);
- if (fd<0)
- xbt_die("Could not open /dev/zero");
- zero_buffer = mmap(NULL, zero_buffer_size, PROT_READ, MAP_SHARED, fd, 0);
- if (zero_buffer == MAP_FAILED)
- xbt_die("Could not map the zero buffer");
- close(fd);
-}
+ unsigned int cursor = 0;
+ IgnoredRegion* current_region = nullptr;
+
+ int start = 0;
+ int end = ignored_regions_.size() - 1;
+ while (start <= end) {
+ cursor = (start + end) / 2;
+ current_region = &ignored_regions_[cursor];
+ if (current_region->addr == addr) {
+ if (current_region->size == size)
+ return;
+ else if (current_region->size < size)
+ start = cursor + 1;
+ else
+ end = cursor - 1;
+ } else if (current_region->addr < addr)
+ start = cursor + 1;
+ else
+ end = cursor - 1;
+ }
-void MC_process_clear_memory(mc_process_t process, void* remote, size_t len)
-{
- if (MC_process_is_self(process)) {
- memset(remote, 0, len);
- } else {
- pthread_once(&zero_buffer_flag, MC_zero_buffer_init);
- while (len) {
- size_t s = len > zero_buffer_size ? zero_buffer_size : len;
- MC_process_write(process, zero_buffer, remote, s);
- remote = (char*) remote + s;
- len -= s;
+ std::size_t position;
+ if (current_region->addr == addr) {
+ if (current_region->size < size) {
+ position = cursor + 1;
+ } else {
+ position = cursor;
}
+ } else if (current_region->addr < addr) {
+ position = cursor + 1;
+ } else {
+ position = cursor;
}
+ ignored_regions_.insert(
+ ignored_regions_.begin() + position, region);
}
}
+}