namespace simgrid {
namespace mc {
-ModelChecker::ModelChecker(pid_t pid, int socket) :
- pid_(pid), socket_(socket),
+ModelChecker::ModelChecker(std::unique_ptr<Process> process) :
hostnames_(xbt_dict_new()),
page_store_(500),
+ process_(std::move(process)),
parent_snapshot_(nullptr)
{
return elt->key;
}
-// HACK, for the unit test only
-void ModelChecker::init_process()
-{
- // TODO, avoid direct dependency on sg_cfg
- process_ = std::unique_ptr<Process>(new Process(pid_, socket_));
- process_->privatized(sg_cfg_get_boolean("smpi/privatize_global_variables"));
-}
-
void ModelChecker::start()
{
+ const pid_t pid = process_->pid();
+
// Block SIGCHLD (this will be handled with accept/signalfd):
sigset_t set;
sigemptyset(&set);
// Prepare data for poll:
struct pollfd* socket_pollfd = &fds_[SOCKET_FD_INDEX];
- socket_pollfd->fd = socket_;
+ socket_pollfd->fd = process_->socket();;
socket_pollfd->events = POLLIN;
socket_pollfd->revents = 0;
int status;
// The model-checked process SIGSTOP itself to signal it's ready:
- pid_t res = waitpid(pid_, &status, __WALL);
+ pid_t res = waitpid(pid, &status, __WALL);
if (res < 0 || !WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP)
xbt_die("Could not wait model-checked process");
- this->init_process();
+ process_->init();
/* Initialize statistics */
mc_stats = xbt_new0(s_mc_stats_t, 1);
setup_ignore();
- ptrace(PTRACE_SETOPTIONS, pid_, nullptr, PTRACE_O_TRACEEXIT);
- ptrace(PTRACE_CONT, pid_, 0, 0);
+ ptrace(PTRACE_SETOPTIONS, pid, nullptr, PTRACE_O_TRACEEXIT);
+ ptrace(PTRACE_CONT, pid, 0, 0);
}
static const std::pair<const char*, const char*> ignored_local_variables[] = {
// From PTRACE_O_TRACEEXIT:
if (status>>8 == (SIGTRAP | (PTRACE_EVENT_EXIT<<8))) {
- if (ptrace(PTRACE_GETEVENTMSG, pid_, 0, &status) == -1)
+ if (ptrace(PTRACE_GETEVENTMSG, this->process().pid(), 0, &status) == -1)
xbt_die("Could not get exit status");
if (WIFSIGNALED(status)) {
MC_report_crash(status);
// We don't care about signals, just reinject them:
if (WIFSTOPPED(status)) {
XBT_DEBUG("Stopped with signal %i", (int) WSTOPSIG(status));
- if (ptrace(PTRACE_CONT, pid_, 0, WSTOPSIG(status)) == -1)
+ if (ptrace(PTRACE_CONT, this->process().pid(), 0, WSTOPSIG(status)) == -1)
xbt_die("Could not PTRACE_CONT");
}
/** State of the model-checker (global variables for the model checker)
*/
class ModelChecker {
- pid_t pid_;
- int socket_;
struct pollfd fds_[2];
/** String pool for host names */
// TODO, use std::unordered_set with heterogeneous comparison lookup (C++14)
public:
ModelChecker(ModelChecker const&) = delete;
ModelChecker& operator=(ModelChecker const&) = delete;
- ModelChecker(pid_t pid, int socket);
+ ModelChecker(std::unique_ptr<Process> process);
~ModelChecker();
Process& process()
}
void start();
- void init_process();
void shutdown();
void resume(simgrid::mc::Process& process);
void loop();
static char* MC_get_lib_name(const char* pathname, struct s_mc_memory_map_re* res)
{
- const char* map_basename = basename((char*) pathname);
+ const char* map_basename = xbt_basename((char*) pathname);
regmatch_t match;
if(regexec(&res->so_re, map_basename, 1, &match, 0))
namespace simgrid {
namespace mc {
-Process::Process(pid_t pid, int sockfd) : AddressSpace(this)
+Process::Process(pid_t pid, int sockfd) :
+ AddressSpace(this),pid_(pid), socket_(sockfd), running_(true)
+{}
+
+void Process::init()
{
- Process* process = this;
- process->socket_ = sockfd;
- process->pid_ = pid;
- process->running_ = true;
- process->memory_map_ = simgrid::xbt::get_memory_map(pid);
- process->cache_flags = MC_PROCESS_CACHE_FLAG_NONE;
- process->init_memory_map_info();
- process->clear_refs_fd_ = -1;
- process->pagemap_fd_ = -1;
- process->privatized_ = false;
-
- int fd = open_vm(process->pid_, O_RDWR);
+ this->memory_map_ = simgrid::xbt::get_memory_map(this->pid_);
+ this->init_memory_map_info();
+
+ int fd = open_vm(this->pid_, O_RDWR);
if (fd<0)
xbt_die("Could not open file for process virtual address space");
- process->memory_file = fd;
+ this->memory_file = fd;
// Read std_heap (is a struct mdesc*):
- simgrid::mc::Variable* std_heap_var = process->find_variable("__mmalloc_default_mdp");
+ simgrid::mc::Variable* std_heap_var = this->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");
- process->read_bytes(&process->heap_address, sizeof(struct mdesc*),
+ this->read_bytes(&this->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->unw_addr_space = unw_create_addr_space(&mc_unw_accessors , __BYTE_ORDER);
- process->unw_underlying_addr_space = unw_create_addr_space(&mc_unw_vmread_accessors, __BYTE_ORDER);
- process->unw_underlying_context = _UPT_create(pid);
+ this->smx_process_infos = MC_smx_process_info_list_new();
+ this->smx_old_process_infos = MC_smx_process_info_list_new();
+ this->unw_addr_space = unw_create_addr_space(&mc_unw_accessors , __BYTE_ORDER);
+ this->unw_underlying_addr_space = unw_create_addr_space(&mc_unw_vmread_accessors, __BYTE_ORDER);
+ this->unw_underlying_context = _UPT_create(this->pid_);
}
Process::~Process()
{
- Process* process = this;
-
if (this->socket_ >= 0 && close(this->socket_) < 0)
xbt_die("Could not close communication socket");
- process->pid_ = 0;
-
- process->maestro_stack_start_ = nullptr;
- process->maestro_stack_end_ = nullptr;
+ this->maestro_stack_start_ = nullptr;
+ this->maestro_stack_end_ = nullptr;
- xbt_dynar_free(&process->smx_process_infos);
- xbt_dynar_free(&process->smx_old_process_infos);
+ xbt_dynar_free(&this->smx_process_infos);
+ xbt_dynar_free(&this->smx_old_process_infos);
- if (process->memory_file >= 0) {
- close(process->memory_file);
+ if (this->memory_file >= 0) {
+ close(this->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);
+ if (this->unw_underlying_addr_space != unw_local_addr_space) {
+ unw_destroy_addr_space(this->unw_underlying_addr_space);
+ _UPT_destroy(this->unw_underlying_context);
}
- process->unw_underlying_context = NULL;
- process->unw_underlying_addr_space = NULL;
+ this->unw_underlying_context = NULL;
+ this->unw_underlying_addr_space = NULL;
- unw_destroy_addr_space(process->unw_addr_space);
- process->unw_addr_space = NULL;
+ unw_destroy_addr_space(this->unw_addr_space);
+ this->unw_addr_space = NULL;
- process->cache_flags = MC_PROCESS_CACHE_FLAG_NONE;
+ this->cache_flags = MC_PROCESS_CACHE_FLAG_NONE;
- if (process->clear_refs_fd_ >= 0)
- close(process->clear_refs_fd_);
- if (process->pagemap_fd_ >= 0)
- close(process->pagemap_fd_);
+ if (this->clear_refs_fd_ >= 0)
+ close(this->clear_refs_fd_);
+ if (this->pagemap_fd_ >= 0)
+ close(this->pagemap_fd_);
}
/** Refresh the information about the process
public:
Process(pid_t pid, int sockfd);
~Process();
+ void init();
Process(Process const&) = delete;
Process(Process &&) = delete;
void unignore_heap(void *address, size_t size);
void ignore_local_variable(const char *var_name, const char *frame_name);
+ int socket() { return socket_; }
private:
void init_memory_map_info();
void refresh_heap();
void refresh_malloc_info();
+
private:
- pid_t pid_;
- int socket_;
- bool running_;
+ pid_t pid_ = -1;
+ int socket_ = -1;
+ bool running_ = false;
std::vector<simgrid::xbt::VmMap> memory_map_;
remote_ptr<void> maestro_stack_start_, maestro_stack_end_;
- int memory_file;
+ int memory_file = -1;
std::vector<IgnoredRegion> ignored_regions_;
- int clear_refs_fd_;
- int pagemap_fd_;
- bool privatized_;
+ int clear_refs_fd_ = -1;
+ int pagemap_fd_ = -1;
+ bool privatized_ = false;
std::vector<s_stack_region_t> stack_areas_;
std::vector<IgnoredHeapRegion> ignored_heap_;
*
* See mc_smx.c.
*/
- xbt_dynar_t smx_process_infos;
+ xbt_dynar_t smx_process_infos = nullptr;
/** Copy of `simix_global->process_to_destroy`
*
* See mc_smx.c.
*/
- xbt_dynar_t smx_old_process_infos;
+ xbt_dynar_t smx_old_process_infos = nullptr;
/** State of the cache (which variables are up to date) */
- mc_process_cache_flags_t cache_flags;
+ mc_process_cache_flags_t cache_flags = MC_PROCESS_CACHE_FLAG_NONE;
/** Address of the heap structure in the MCed process. */
void* heap_address;
simgrid::mc::ObjectInformation* result)
{
char* file_name = xbt_strdup(result->file_name.c_str());
- const char *name = basename(file_name);
+ const char *name = xbt_basename(file_name);
for (size_t i = 0; i < maps.size(); ++i) {
simgrid::xbt::VmMap const& reg = maps[i];
if (maps[i].pathname.empty()
- || strcmp(basename(maps[i].pathname.c_str()), name)) {
+ || strcmp(xbt_basename(maps[i].pathname.c_str()), name)) {
// Nothing to do
} else if ((reg.prot & PROT_WRITE)) {
xbt_assert(!result->start_rw,
continue;
// If dot_output enabled, do not handle the corresponding file
- if (dot_output != NULL && strcmp(basename(link), _sg_mc_dot_output_file) == 0)
+ if (dot_output != NULL && strcmp(xbt_basename(link), _sg_mc_dot_output_file) == 0)
continue;
// This is probably a shared memory used by lttng-ust:
_sg_mc_sparse_checkpoint = sparse_checkpoint;
xbt_assert(xbt_pagesize == getpagesize());
xbt_assert(1 << xbt_pagebits == xbt_pagesize);
- mc_model_checker = new ::simgrid::mc::ModelChecker(getpid(), -1);
- mc_model_checker->init_process();
+
+ std::unique_ptr<simgrid::mc::Process> process(new simgrid::mc::Process(getpid(), -1));
+ process->init();
+ mc_model_checker = new ::simgrid::mc::ModelChecker(std::move(process));
for(int n=1; n!=256; ++n) {
xbt_die("MC server already present");
try {
mc_mode = MC_MODE_SERVER;
- mc_model_checker = new simgrid::mc::ModelChecker(child, socket);
+ std::unique_ptr<simgrid::mc::Process> process(new simgrid::mc::Process(child, socket));
+ process->privatized(sg_cfg_get_boolean("smpi/privatize_global_variables"));
+ mc_model_checker = new simgrid::mc::ModelChecker(std::move(process));
mc_model_checker->start();
int res = 0;
if (_sg_mc_comms_determinism || _sg_mc_send_determinism)
}
if (result && !acyclic_graph_detail(result)) {
- XBT_ERROR("The DOT described in %s is not a DAG. It contains a cycle.", basename((char*)filename));
+ XBT_ERROR("The DOT described in %s is not a DAG. It contains a cycle.", xbt_basename((char*)filename));
xbt_dynar_free(&result);
result = NULL;
}
}
-static simgrid::mc::Variable* test_global_variable(simgrid::mc::Process* process, simgrid::mc::ObjectInformation* info, const char* name, void* address, long byte_size) {
-
+static simgrid::mc::Variable* test_global_variable(
+ simgrid::mc::Process& process, simgrid::mc::ObjectInformation* info,
+ const char* name, void* address, long byte_size)
+{
simgrid::mc::Variable* variable = info->find_variable(name);
xbt_assert(variable, "Global variable %s was not found", name);
xbt_assert(variable->name == name,
"Address mismatch for %s : %p expected but %p found",
name, address, variable->address);
- auto i = process->binary_info->types.find(variable->type_id);
- xbt_assert(i != process->binary_info->types.end(), "Missing type for %s", name);
+ auto i = process.binary_info->types.find(variable->type_id);
+ xbt_assert(i != process.binary_info->types.end(), "Missing type for %s", name);
simgrid::mc::Type* type = &i->second;
xbt_assert(type->byte_size = byte_size, "Byte size mismatch for %s", name);
return variable;
typedef struct foo {int i;} s_foo;
-static void test_type_by_name(simgrid::mc::Process* process, s_foo my_foo)
+static void test_type_by_name(simgrid::mc::Process& process, s_foo my_foo)
{
assert(
- process->binary_info->full_types_by_name.find("struct foo") !=
- process->binary_info->full_types_by_name.end());
+ process.binary_info->full_types_by_name.find("struct foo") !=
+ process.binary_info->full_types_by_name.end());
}
int main(int argc, char** argv)
simgrid::mc::Variable* var;
simgrid::mc::Type* type;
- simgrid::mc::Process p(getpid(), -1);
- simgrid::mc::Process* process = &p;
+ simgrid::mc::Process process(getpid(), -1);
+ process.init();
- test_global_variable(process, process->binary_info.get(),
+ test_global_variable(process, process.binary_info.get(),
"some_local_variable", &some_local_variable, sizeof(int));
- var = test_global_variable(process, process->binary_info.get(),
+ var = test_global_variable(process, process.binary_info.get(),
"test_some_array", &test_some_array, sizeof(test_some_array));
- auto i = process->binary_info->types.find(var->type_id);
- xbt_assert(i != process->binary_info->types.end(), "Missing type");
+ auto i = process.binary_info->types.find(var->type_id);
+ xbt_assert(i != process.binary_info->types.end(), "Missing type");
type = &i->second;
xbt_assert(type->element_count == 6*5*4,
"element_count mismatch in test_some_array : %i / %i",
type->element_count, 6*5*4);
- var = test_global_variable(process, process->binary_info.get(),
+ var = test_global_variable(process, process.binary_info.get(),
"test_some_struct", &test_some_struct, sizeof(test_some_struct));
- i = process->binary_info->types.find(var->type_id);
- xbt_assert(i != process->binary_info->types.end(), "Missing type");
+ i = process.binary_info->types.find(var->type_id);
+ xbt_assert(i != process.binary_info->types.end(), "Missing type");
type = &i->second;
assert(type);
unw_getcontext(&context);
unw_init_local(&cursor, &context);
- test_local_variable(process->binary_info.get(), "main", "argc", &argc, &cursor);
+ test_local_variable(process.binary_info.get(), "main", "argc", &argc, &cursor);
{
int lexical_block_variable = 50;
- test_local_variable(process->binary_info.get(), "main",
+ test_local_variable(process.binary_info.get(), "main",
"lexical_block_variable", &lexical_block_variable, &cursor);
}
int main(int argc, char** argv) {
process = new simgrid::mc::Process(getpid(), -1);
+ process->init();
simgrid::dwarf::ExpressionContext state;
state.address_space = (simgrid::mc::AddressSpace*) process;
-#!/usr/bin/env perl
+#!/usr/bin/env python
# Compiler wrapper with stack-cleaner support (enabled by default).
# Usage: ./compiler-wrapper target-compiler args [-f[no-]stack-cleaner]
-use warnings;
+import sys
+import os
+import re
-use File::Basename;
+compiler = sys.argv[1]
+enabled = True
+args = []
-my $compiler = shift(@ARGV);
+for arg in sys.argv[2:]:
+ if arg == "--help":
+ sys.stderr.write(
+ "Compiler wrapper with stack-cleaner.\n"
+ "Usage: {} compiler [-f[no-]stack-cleaner] [options]\n".format(sys.argv[0]))
+ sys.exit(0)
+ elif arg == "-fno-stack-cleaner":
+ enabled = False
+ elif arg == "-fstack-cleaner":
+ enabled = True
+ else:
+ args.append(arg)
-my $enable = 1;
+if enabled:
+ if re.match("^clang", os.path.basename(compiler)):
+ args.insert(0, "-no-integrated-as")
+ args.insert(0, os.path.dirname(sys.argv[0]))
+ args.insert(0, "-B")
+args.insert(0, compiler)
-my @args;
-my $arg;
-while($arg=shift(@ARGV)) {
- if ($arg eq "-fno-stack-cleaner") {
- $enable = 0;
- } elsif ($arg eq "-fstack-cleaner") {
- $enable = 1;
- }
- else {
- push @args, $arg;
- }
-}
-
-if ($enable) {
- if (basename($0) =~ /^clang/) {
- unshift @args, "-no-integrated-as"
- }
- unshift @args, dirname($0);
- unshift @args, "-B";
-}
-
-exec $compiler, @args
+os.execvp(args[0], args)
+sys.stderr.write("compiler-wrapper: Could not exec\n")
+os.exit(1)