-/* Copyright (c) 2014-2017. The SimGrid Team. All rights reserved. */
+/* Copyright (c) 2014-2020. 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. */
#define _FILE_OFFSET_BITS 64 /* needed for pread_whole to work as expected on 32bits */
-#include <algorithm>
-#include <cassert>
-#include <cerrno>
-#include <cstddef>
-#include <cstdint>
-#include <regex>
-#include <string>
-#include <vector>
-
-#include <sys/ptrace.h>
-
-#include <cstdio>
-
-#include <fcntl.h>
-#include <sys/mman.h> // PROT_*
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <pthread.h>
-
-#include <libgen.h>
-
-#include <libunwind-ptrace.h>
-#include <libunwind.h>
+#include "src/mc/remote/RemoteClient.hpp"
-#include "xbt/base.h"
+#include "src/mc/mc_smx.hpp"
+#include "src/mc/sosp/Snapshot.hpp"
#include "xbt/file.hpp"
#include "xbt/log.h"
-#include <xbt/mmalloc.h>
-
-#include "src/mc/mc_smx.hpp"
-#include "src/mc/mc_snapshot.hpp"
-#include "src/mc/mc_unw.hpp"
-#include "src/mc/AddressSpace.hpp"
-#include "src/mc/ObjectInformation.hpp"
-#include "src/mc/Variable.hpp"
-#include "src/mc/remote/RemoteClient.hpp"
+#include <fcntl.h>
+#include <libunwind-ptrace.h>
+#include <sys/mman.h> // PROT_*
using simgrid::mc::remote;
"libthr", /* thread library */
"libutil",
#endif
- "libasan", /* gcc sanitizers */
"libargp", /* workarounds for glibc-less systems */
- "libtsan",
- "libubsan",
- "libbz2",
+ "libasan", /* gcc sanitizers */
"libboost_chrono",
"libboost_context",
"libboost_context-mt",
+ "libboost_stacktrace_addr2line",
+ "libboost_stacktrace_backtrace",
"libboost_system",
"libboost_thread",
+ "libboost_timer",
+ "libbz2",
"libc",
"libc++",
"libcdt",
"libdw",
"libelf",
"libevent",
+ "libexecinfo",
+ "libflang",
+ "libflangrti",
"libgcc_s",
+ "libgfortran",
+ "libimf",
+ "libintlc",
+ "libirng",
"liblua5.1",
"liblua5.3",
"liblzma",
"libm",
+ "libomp",
+ "libpapi",
+ "libpcre2",
+ "libpfm",
+ "libpgmath",
"libpthread",
+ "libquadmath",
"librt",
"libstdc++",
+ "libsvml",
+ "libtsan", /* gcc sanitizers */
+ "libubsan", /* gcc sanitizers */
"libunwind",
- "libunwind-x86_64",
- "libunwind-x86",
"libunwind-ptrace",
- "libz"};
+ "libunwind-x86",
+ "libunwind-x86_64",
+ "libz",
+ "libkrb5support", /*odd behaviour on fedora rawhide ... remove these when fixed*/
+ "libkeyutils",
+ "libunistring",
+ "libbrotlidec",
+ "liblber",
+ "libldap",
+ "libcom_err",
+ "libk5crypto",
+ "libkrb5",
+ "libgssapi_krb5",
+ "libssl",
+ "libpsl",
+ "libssh",
+ "libidn2",
+ "libnghttp2",
+ "libcurl",
+ "libdebuginfod",
+ "libbrotlicommon",
+ "libsasl2",
+ "libresolv",
+ "libcrypt",
+ "libselinux"
+};
static bool is_simgrid_lib(const std::string& libname)
{
static std::string get_lib_name(const std::string& pathname)
{
- static const std::regex so_re("\\.so[.0-9]*$");
- static const std::regex version_re("-[.0-9-]*$");
- std::string map_basename = simgrid::xbt::Path(pathname).getBasename();
+ std::string map_basename = simgrid::xbt::Path(pathname).get_base_name();
std::string libname;
- std::smatch match;
- if (std::regex_search(map_basename, match, so_re)) {
- libname = match.prefix();
-
- // Strip the version suffix:
- if (std::regex_search(libname, match, version_re))
- libname = match.prefix();
+ size_t pos = map_basename.rfind(".so");
+ if (pos != std::string::npos) {
+ // strip the extension (matching regex "\.so.*$")
+ libname.assign(map_basename, 0, pos);
+
+ // strip the version suffix (matching regex "-[.0-9-]*$")
+ while (true) {
+ pos = libname.rfind('-');
+ if (pos == std::string::npos || libname.find_first_not_of(".0123456789", pos + 1) != std::string::npos)
+ break;
+ libname.erase(pos);
+ }
}
return libname;
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");
+ xbt_assert(fd >= 0, "Could not open file for process virtual address space");
this->memory_file = fd;
// Read std_heap (is a struct mdesc*):
- simgrid::mc::Variable* std_heap_var = this->find_variable("__mmalloc_default_mdp");
- if (not std_heap_var)
- xbt_die("No heap information in the target process");
- if (not std_heap_var->address)
- xbt_die("No constant address for this variable");
- this->read_bytes(&this->heap_address, sizeof(mdesc*), remote(std_heap_var->address),
- simgrid::mc::ProcessIndexDisabled);
+ const simgrid::mc::Variable* std_heap_var = this->find_variable("__mmalloc_default_mdp");
+ xbt_assert(std_heap_var, "No heap information in the target process");
+ xbt_assert(std_heap_var->address, "No constant address for this variable");
+ this->read_bytes(&this->heap_address, sizeof(mdesc*), remote(std_heap_var->address));
this->smx_actors_infos.clear();
this->smx_dead_actors_infos.clear();
{
// Read/dereference/refresh the std_heap pointer:
if (not this->heap)
- this->heap = std::unique_ptr<s_xbt_mheap_t>(new s_xbt_mheap_t());
- this->read_bytes(this->heap.get(), sizeof(mdesc), remote(this->heap_address), simgrid::mc::ProcessIndexDisabled);
+ this->heap.reset(new s_xbt_mheap_t());
+ this->read_bytes(this->heap.get(), sizeof(mdesc), remote(this->heap_address));
this->cache_flags_ |= RemoteClient::cache_heap;
}
/** Refresh the information about the process
*
- * Do not use direclty, this is used by the getters when appropriate
+ * Do not use directly, this is used by the getters when appropriate
* in order to have fresh data.
* */
void RemoteClient::refresh_malloc_info()
size_t count = this->heap->heaplimit + 1;
if (this->heap_info.size() < count)
this->heap_info.resize(count);
- this->read_bytes(this->heap_info.data(), count * sizeof(malloc_info), remote(this->heap->heapinfo),
- simgrid::mc::ProcessIndexDisabled);
+ this->read_bytes(this->heap_info.data(), count * sizeof(malloc_info), remote(this->heap->heapinfo));
this->cache_flags_ |= RemoteClient::cache_malloc;
}
/** Find (one occurrence of) the named variable definition
*/
-simgrid::mc::Variable* RemoteClient::find_variable(const char* name) const
+const simgrid::mc::Variable* RemoteClient::find_variable(const char* name) const
{
// 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.
+ // is reinstantiated in the executable memory .data/.bss.
// We need to look up the variable in the executable first.
if (this->binary_info) {
std::shared_ptr<simgrid::mc::ObjectInformation> const& info = this->binary_info;
- simgrid::mc::Variable* var = info->find_variable(name);
+ const simgrid::mc::Variable* var = info->find_variable(name);
if (var)
return var;
}
for (std::shared_ptr<simgrid::mc::ObjectInformation> const& info : this->object_infos) {
- simgrid::mc::Variable* var = info->find_variable(name);
+ const simgrid::mc::Variable* var = info->find_variable(name);
if (var)
return var;
}
void RemoteClient::read_variable(const char* name, void* target, size_t size) const
{
- simgrid::mc::Variable* var = this->find_variable(name);
+ const simgrid::mc::Variable* var = this->find_variable(name);
+ xbt_assert(var, "Variable %s not found", name);
xbt_assert(var->address, "No simple location for this variable");
xbt_assert(var->type->full_type, "Partial type for %s, cannot check size", name);
xbt_assert((size_t)var->type->full_type->byte_size == size, "Unexpected size for %s (expected %zu, was %zu)", name,
if (not address)
return {};
- // TODO, use std::vector with .data() in C++17 to avoid useless copies
std::vector<char> res(128);
off_t off = 0;
while (1) {
ssize_t c = pread(this->memory_file, res.data() + off, res.size() - off, (off_t)address.address() + off);
- if (c == -1) {
- if (errno == EINTR)
- continue;
- else
- xbt_die("Could not read from from remote process");
- }
- if (c == 0)
- xbt_die("Could not read string from remote process");
+ if (c == -1 && errno == EINTR)
+ continue;
+ xbt_assert(c > 0, "Could not read string from remote process");
- void* p = memchr(res.data() + off, '\0', c);
+ const void* p = memchr(res.data() + off, '\0', c);
if (p)
return std::string(res.data());
}
}
-const void* RemoteClient::read_bytes(void* buffer, std::size_t size, RemotePtr<void> address, int process_index,
- ReadOptions options) const
+void* RemoteClient::read_bytes(void* buffer, std::size_t size, RemotePtr<void> address, ReadOptions /*options*/) const
{
- if (process_index != simgrid::mc::ProcessIndexDisabled) {
- std::shared_ptr<simgrid::mc::ObjectInformation> const& info = this->find_object_info_rw((void*)address.address());
-// Segment overlap is not handled.
-#if HAVE_SMPI
- if (info.get() && this->privatized(*info)) {
- if (process_index < 0)
- xbt_die("Missing process index");
- if (process_index >= (int)MC_smpi_process_count())
- xbt_die("Invalid process index");
-
- // Read smpi_privatization_regions from MCed:
- smpi_privatization_region_t remote_smpi_privatization_regions =
- mc_model_checker->process().read_variable<smpi_privatization_region_t>("smpi_privatization_regions");
-
- s_smpi_privatization_region_t privatization_region =
- mc_model_checker->process().read<s_smpi_privatization_region_t>(
- remote(remote_smpi_privatization_regions + process_index));
-
- // Address translation in the privatization segment:
- size_t offset = address.address() - (std::uint64_t)info->start_rw;
- address = remote((char*)privatization_region.address + offset);
- }
-#endif
- }
if (pread_whole(this->memory_file, buffer, size, (size_t)address.address()) < 0)
xbt_die("Read at %p from process %lli failed", (void*)address.address(), (long long)this->pid_);
return buffer;
}
unsigned int cursor = 0;
- IgnoredRegion* current_region = nullptr;
+ const IgnoredRegion* current_region = nullptr;
int start = 0;
int end = ignored_regions_.size() - 1;
size_type cursor;
while (start <= end) {
cursor = start + (end - start) / 2;
- auto& current_region = ignored_heap_[cursor];
+ auto const& current_region = ignored_heap_[cursor];
if (current_region.address == region.address)
return;
else if (current_region.address < region.address)
size_type cursor;
while (start <= end) {
cursor = (start + end) / 2;
- auto& region = ignored_heap_[cursor];
- if (region.address == address) {
- ignored_heap_.erase(ignored_heap_.begin() + cursor);
- return;
- } else if (region.address < address)
+ auto const& region = ignored_heap_[cursor];
+ if (region.address < address)
start = cursor + 1;
else if ((char*)region.address <= ((char*)address + size)) {
ignored_heap_.erase(ignored_heap_.begin() + cursor);
return smx_dead_actors_infos;
}
-void RemoteClient::dumpStack()
+void RemoteClient::dump_stack()
{
unw_addr_space_t as = unw_create_addr_space(&_UPT_accessors, BYTE_ORDER);
if (as == nullptr) {
return;
}
- simgrid::mc::dumpStack(stderr, cursor);
+ simgrid::mc::dumpStack(stderr, &cursor);
_UPT_destroy(context);
unw_destroy_addr_space(as);
- return;
}
bool RemoteClient::actor_is_enabled(aid_t pid)
{
- s_mc_message_actor_enabled msg{MC_MESSAGE_ACTOR_ENABLED, pid};
- process()->getChannel().send(msg);
+ s_mc_message_actor_enabled_t msg{MC_MESSAGE_ACTOR_ENABLED, pid};
+ process()->get_channel().send(msg);
char buff[MC_MESSAGE_LENGTH];
- ssize_t received = process()->getChannel().receive(buff, MC_MESSAGE_LENGTH, true);
- xbt_assert(received == sizeof(s_mc_message_int), "Unexpected size in answer to ACTOR_ENABLED");
- return ((mc_message_int_t*)buff)->value;
+ ssize_t received = process()->get_channel().receive(buff, MC_MESSAGE_LENGTH, true);
+ xbt_assert(received == sizeof(s_mc_message_int_t), "Unexpected size in answer to ACTOR_ENABLED");
+ return ((s_mc_message_int_t*)buff)->value;
}
}
}