From: Gabriel Corona Date: Tue, 3 Nov 2015 13:05:14 +0000 (+0100) Subject: [smpi] Use virtual memory layout to find the data segment X-Git-Tag: v3_13~1595^2 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/3bda7845c0cceaaeedd5d0371434927c8cf6231d?hp=9cf73cc09740865d0de90546a12b2e2d74cfaf6f [smpi] Use virtual memory layout to find the data segment ... Instead of extrating the position of the .data and .bss sections with objdump: * don't spawn a separate process (objdump); * works even with PIE; * works even without section header table; * works even if weird sections are used; * works at the segment granuality instead of the section granularity. However some heuristic is used which might break in some cases: using the help of the program header table would be a good idea (but would add a dependency on ELF). Currently only implemented on Linux but the SMPI privatisation was only available on Linux anyway. --- diff --git a/CMakeLists.txt b/CMakeLists.txt index d80201ac58..e46f6b888c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -434,14 +434,12 @@ endif() if(enable_smpi) include(FindGFortran) - #really checks for objdump for privatization - find_package(BinUtils QUIET) - mark_as_advanced(BinUtils_DIR) SET(HAVE_SMPI 1) - - if( NOT "${CMAKE_OBJDUMP}" MATCHES "CMAKE_OBJDUMP-NOTFOUND" AND HAVE_MMAP) + if("${CMAKE_SYSTEM}" MATCHES "Linux") + SET(USE_LIBUTIL 0) SET(HAVE_PRIVATIZATION 1) - else() + elseif("${CMAKE_SYSTEM}" MATCHES "^FreeBSD") + SET(USE_LIBUTIL 0) SET(HAVE_PRIVATIZATION 0) endif() endif() diff --git a/src/mc/Process.cpp b/src/mc/Process.cpp index ea58d759c0..b001926912 100644 --- a/src/mc/Process.cpp +++ b/src/mc/Process.cpp @@ -214,7 +214,7 @@ Process::Process(pid_t pid, int sockfd) : AddressSpace(this) process->pid_ = pid; process->running_ = true; process->status_ = 0; - process->memory_map_ = get_memory_map(pid); + 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; @@ -329,14 +329,14 @@ void Process::init_memory_map_info() if(regcomp(&res.so_re, SO_RE, 0) || regcomp(&res.version_re, VERSION_RE, 0)) xbt_die(".so regexp did not compile"); - std::vector const& maps = this->memory_map_; + std::vector const& maps = this->memory_map_; const char* current_name = NULL; this->object_infos.resize(0); for (size_t i=0; i < maps.size(); i++) { - simgrid::mc::VmMap const& reg = maps[i]; + simgrid::xbt::VmMap const& reg = maps[i]; const char* pathname = maps[i].pathname.c_str(); // Nothing to do diff --git a/src/mc/Process.hpp b/src/mc/Process.hpp index 223711acc2..6cc3cfdea7 100644 --- a/src/mc/Process.hpp +++ b/src/mc/Process.hpp @@ -28,10 +28,11 @@ #include "src/simix/popping_private.h" #include "src/simix/smx_private.h" +#include "../xbt/memory_map.hpp" + #include "mc_forward.hpp" #include "mc_base.h" #include "mc_mmalloc.h" // std_heap -#include "mc_memory_map.h" #include "AddressSpace.hpp" #include "mc_protocol.h" @@ -163,7 +164,7 @@ private: int socket_; int status_; bool running_; - std::vector memory_map_; + std::vector memory_map_; remote_ptr maestro_stack_start_, maestro_stack_end_; int memory_file; std::vector ignored_regions_; diff --git a/src/mc/mc_checkpoint.cpp b/src/mc/mc_checkpoint.cpp index 01c518386c..f458f72a84 100644 --- a/src/mc/mc_checkpoint.cpp +++ b/src/mc/mc_checkpoint.cpp @@ -11,7 +11,6 @@ #include #include "src/internal_config.h" -#include "mc_memory_map.h" #include "mc_private.h" #include "xbt/module.h" #include @@ -197,13 +196,13 @@ static void MC_get_memory_regions(simgrid::mc::Process* process, mc_snapshot_t s * `dl_iterate_phdr` would be more robust but would not work in cross-process. * */ void MC_find_object_address( - std::vector const& maps, + std::vector const& maps, simgrid::mc::ObjectInformation* result) { char* file_name = xbt_strdup(result->file_name.c_str()); const char *name = basename(file_name); for (size_t i = 0; i < maps.size(); ++i) { - simgrid::mc::VmMap const& reg = maps[i]; + simgrid::xbt::VmMap const& reg = maps[i]; if (maps[i].pathname.empty() || strcmp(basename(maps[i].pathname.c_str()), name)) { // Nothing to do @@ -214,7 +213,7 @@ void MC_find_object_address( result->start_rw = (char*) reg.start_addr; result->end_rw = (char*) reg.end_addr; // .bss is usually after the .data: - simgrid::mc::VmMap const& next = maps[i + 1]; + simgrid::xbt::VmMap const& next = maps[i + 1]; if (next.pathname.empty() && (next.prot & PROT_WRITE) && next.start_addr == reg.end_addr) { result->end_rw = (char*) maps[i + 1].end_addr; diff --git a/src/mc/mc_dwarf.cpp b/src/mc/mc_dwarf.cpp index efce4fd887..c744d0aec6 100644 --- a/src/mc/mc_dwarf.cpp +++ b/src/mc/mc_dwarf.cpp @@ -1149,7 +1149,7 @@ static void MC_post_process_types(simgrid::mc::ObjectInformation* info) /** \brief Finds informations about a given shared object/executable */ std::shared_ptr MC_find_object_info( - std::vector const& maps, const char *name) + std::vector const& maps, const char *name) { std::shared_ptr result = std::make_shared(); diff --git a/src/mc/mc_dwarf.hpp b/src/mc/mc_dwarf.hpp index 4ddeaa72f7..85c7641e7b 100644 --- a/src/mc/mc_dwarf.hpp +++ b/src/mc/mc_dwarf.hpp @@ -17,7 +17,6 @@ #include #include "src/mc/Variable.hpp" -#include "src/mc/mc_memory_map.h" namespace simgrid { namespace dwarf { diff --git a/src/mc/mc_global.cpp b/src/mc/mc_global.cpp index 7ead3c543c..3fe3677bf9 100644 --- a/src/mc/mc_global.cpp +++ b/src/mc/mc_global.cpp @@ -36,7 +36,6 @@ #include "mc_comm_pattern.h" #include "mc_request.h" #include "mc_safety.h" -#include "mc_memory_map.h" #include "mc_snapshot.h" #include "mc_liveness.h" #include "mc_private.h" diff --git a/src/mc/mc_object_info.h b/src/mc/mc_object_info.h index d8df6b23a3..840d3e1ab6 100644 --- a/src/mc/mc_object_info.h +++ b/src/mc/mc_object_info.h @@ -13,10 +13,10 @@ #include #include "mc_forward.hpp" -#include "mc_memory_map.h" +#include "../xbt/memory_map.hpp" XBT_PRIVATE std::shared_ptr MC_find_object_info( - std::vector const& maps, const char* name); + std::vector const& maps, const char* name); XBT_PRIVATE void MC_post_process_object_info(simgrid::mc::Process* process, simgrid::mc::ObjectInformation* info); #endif diff --git a/src/mc/mc_private.h b/src/mc/mc_private.h index bbd2a64823..b21b6a5cbf 100644 --- a/src/mc/mc_private.h +++ b/src/mc/mc_private.h @@ -24,6 +24,10 @@ #include "xbt/fifo.h" #include "xbt/config.h" +#ifdef __cplusplus +#include "../xbt/memory_map.hpp" +#endif + #include "xbt/function_types.h" #include "xbt/mmalloc.h" #include "../simix/smx_private.h" @@ -118,6 +122,13 @@ XBT_PRIVATE void MC_report_assertion_error(void); XBT_PRIVATE void MC_invalidate_cache(void); +#ifdef __cplusplus + +XBT_PRIVATE void MC_find_object_address( + std::vector const& maps, simgrid::mc::ObjectInformation* result); + +#endif + SG_END_DECL() #endif diff --git a/src/smpi/smpi_bench.c b/src/smpi/smpi_bench.c index 6dbbddb77c..76bc4382b7 100644 --- a/src/smpi/smpi_bench.c +++ b/src/smpi/smpi_bench.c @@ -644,82 +644,6 @@ int smpi_is_privatisation_file(char* file) return strncmp("/dev/shm/my-buffer-", file, 19) == 0; } -void smpi_get_executable_global_size(){ - int size_bss_binary=0; - int size_data_binary=0; - FILE *fp; - char *line = NULL; /* Temporal storage for each line that is readed */ - ssize_t read; /* Number of bytes readed */ - size_t n = 0; /* Amount of bytes to read by xbt_getline */ - - char *lfields[7]; - int i, found = 0; - - char *command = bprintf("objdump --section-headers %s", xbt_binary_name); - - fp = popen(command, "r"); - - if(fp == NULL){ - perror("popen failed"); - xbt_abort(); - } - - while ((read = xbt_getline(&line, &n, fp)) != -1 && found != 2) { - - if(n == 0) - continue; - - /* Wipeout the new line character */ - line[read - 1] = '\0'; - - lfields[0] = strtok(line, " "); - - if(lfields[0] == NULL) - continue; - - if(strcmp(lfields[0], "Sections:") == 0 - || strcmp(lfields[0], "Idx") == 0 - || strncmp(lfields[0], xbt_binary_name, strlen(xbt_binary_name)) == 0) - continue; - - for (i = 1; i < 7 && lfields[i - 1] != NULL; i++) { - lfields[i] = strtok(NULL, " "); - } - - /* - * we are looking for these fields - 23 .data 02625a20 00000000006013e0 00000000006013e0 000013e0 2**5 - CONTENTS, ALLOC, LOAD, DATA - 24 .bss 02625a40 0000000002c26e00 0000000002c26e00 02626e00 2**5 - ALLOC - */ - - if(i>=6){ - if(strcmp(lfields[1], ".data") == 0){ - size_data_binary = strtoul(lfields[2], NULL, 16); - smpi_start_data_exe = (char*) strtoul(lfields[4], NULL, 16); - found++; - }else if(strcmp(lfields[1], ".bss") == 0){ - //the beginning of bss is not exactly the end of data if not aligned, grow bss reported size accordingly - //TODO : check if this is OK, as some segments may be inserted between them.. - size_bss_binary = ((char*) strtoul(lfields[4], NULL, 16) - (smpi_start_data_exe + size_data_binary)) - + strtoul(lfields[2], NULL, 16); - found++; - } - - } - - } - - smpi_size_data_exe = (unsigned long) smpi_start_data_exe - - (unsigned long) TOPAGE(smpi_start_data_exe) - + size_data_binary+size_bss_binary; - xbt_free(command); - xbt_free(line); - pclose(fp); - -} - void smpi_initialize_global_memory_segments(){ #ifndef HAVE_PRIVATIZATION diff --git a/src/smpi/smpi_memory.cpp b/src/smpi/smpi_memory.cpp new file mode 100644 index 0000000000..34e3d8fc1e --- /dev/null +++ b/src/smpi/smpi_memory.cpp @@ -0,0 +1,59 @@ +/* Copyright (c) 2015. 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 + +#include +#include +#include +#include +#include + +#include "../xbt/memory_map.hpp" + +#include "private.h" + +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_memory, smpi, + "Memory layout support for SMPI"); + +#define TOPAGE(addr) (void *)(((unsigned long)(addr) / xbt_pagesize) * xbt_pagesize) + +#define PROT_RWX (PROT_READ | PROT_WRITE | PROT_EXEC) +#define PROT_RW (PROT_READ | PROT_WRITE ) +#define PROT_RX (PROT_READ | PROT_EXEC ) + +void smpi_get_executable_global_size(void) +{ + char buffer[PATH_MAX]; + char* full_name = realpath(xbt_binary_name, buffer); + if (full_name == nullptr) + xbt_die("Could not resolve binary file name"); + + std::vector map = simgrid::xbt::get_memory_map(getpid()); + for (auto i = map.begin(); i != map.end() ; ++i) { + // TODO, In practice, this implementation would not detect a completely + // anonymous data segment. This does not happen in practice, however. + + // File backed RW entry: + if (i->pathname == full_name + && (i->prot & PROT_RWX) == PROT_RW) { + smpi_start_data_exe = (char*) i->start_addr; + smpi_size_data_exe = i->end_addr - i->start_addr; + ++i; + /* Here we are making the assumption that a suitable empty region + following the rw- area is the end of the data segment. It would + be better to check with the size of the data segment. */ + if (i != map.end() + && i->pathname.empty() + && (i->prot & PROT_RWX) == PROT_RW + && i->start_addr == (std::uint64_t) smpi_start_data_exe + smpi_size_data_exe) { + smpi_size_data_exe = i->end_addr - (std::uint64_t) smpi_start_data_exe; + } + return; + } + } + xbt_die("Did not find my data segment."); +} diff --git a/src/xbt/log.c b/src/xbt/log.c index 0ce0cd4552..8cb2f84564 100644 --- a/src/xbt/log.c +++ b/src/xbt/log.c @@ -644,7 +644,6 @@ static void xbt_log_connect_categories(void) XBT_LOG_CONNECT(mcer_ignore); XBT_LOG_CONNECT(mc_liveness); XBT_LOG_CONNECT(mc_memory); - XBT_LOG_CONNECT(mc_memory_map); XBT_LOG_CONNECT(mc_page_snapshot); XBT_LOG_CONNECT(mc_request); XBT_LOG_CONNECT(mc_safety); diff --git a/src/mc/memory_map.cpp b/src/xbt/memory_map.cpp similarity index 91% rename from src/mc/memory_map.cpp rename to src/xbt/memory_map.cpp index f13f9af329..0fc10cba9e 100644 --- a/src/mc/memory_map.cpp +++ b/src/xbt/memory_map.cpp @@ -9,24 +9,28 @@ #include #include +#include +#include #include +#include +#include -#include "mc_memory_map.h" -#include "mc_private.h" +#include "memory_map.hpp" extern "C" { -XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_memory_map, mc, +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_memory_map, xbt, "Logging specific to algorithms for memory_map"); } namespace simgrid { -namespace mc { +namespace xbt { XBT_PRIVATE std::vector get_memory_map(pid_t pid) { +#ifdef __linux__ /* Open the actual process's proc maps file and create the memory_map_t */ /* to be returned. */ char* path = bprintf("/proc/%i/maps", (int) pid); @@ -162,6 +166,11 @@ XBT_PRIVATE std::vector get_memory_map(pid_t pid) std::free(line); std::fclose(fp); return std::move(ret); +#else + /* On FreeBSD, kinfo_getvmmap() could be used but mmap() support is disabled + anyway. */ + xbt_die("Could not get memory map from process %lli", (long long int) pid); +#endif } } diff --git a/src/mc/mc_memory_map.h b/src/xbt/memory_map.hpp similarity index 78% rename from src/mc/mc_memory_map.h rename to src/xbt/memory_map.hpp index 786085486c..e4e138d6d1 100644 --- a/src/mc/mc_memory_map.h +++ b/src/xbt/memory_map.hpp @@ -4,23 +4,18 @@ /* 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 SIMGRID_MC_MEMORY_MAP_H -#define SIMGRID_MC_MEMORY_MAP_H +#ifndef SIMGRID_XBT_MEMORY_MAP_HPP +#define SIMGRID_XBT_MEMORY_MAP_HPP #include - #include #include -#include - #include - -#include -#include "mc_forward.hpp" +#include namespace simgrid { -namespace mc { +namespace xbt { /** An virtual memory map entry from /proc/$pid/maps */ struct VmMap { @@ -39,11 +34,4 @@ XBT_PRIVATE std::vector get_memory_map(pid_t pid); } } -extern "C" { - -XBT_PRIVATE void MC_find_object_address( - std::vector const& maps, simgrid::mc::ObjectInformation* result); - -} - #endif diff --git a/tools/cmake/DefinePackages.cmake b/tools/cmake/DefinePackages.cmake index 360eb6c7aa..6f50c773fc 100644 --- a/tools/cmake/DefinePackages.cmake +++ b/tools/cmake/DefinePackages.cmake @@ -105,6 +105,7 @@ set(EXTRA_DIST src/xbt/heap_private.h src/xbt/log_private.h src/xbt/mallocator_private.h + src/xbt/mmalloc/mfree.c src/xbt/mmalloc/mm.c src/xbt/mmalloc/mm_legacy.c @@ -229,6 +230,7 @@ set(SMPI_SRC src/smpi/instr_smpi.c src/smpi/smpi_base.c src/smpi/smpi_bench.c + src/smpi/smpi_memory.cpp src/smpi/smpi_c99.c src/smpi/smpi_coll.c src/smpi/smpi_comm.c @@ -264,6 +266,8 @@ set(XBT_SRC src/xbt/lib.c src/xbt/log.c src/xbt/mallocator.c + src/xbt/memory_map.cpp + src/xbt/memory_map.hpp src/xbt/parmap.cpp src/xbt/set.c src/xbt/snprintf.c @@ -284,6 +288,7 @@ set(XBT_SRC src/xbt/xbt_strbuff.c src/xbt/xbt_virtu.c src/xbt_modinter.h + ) if(HAVE_MMALLOC) @@ -673,8 +678,6 @@ set(MC_SRC src/mc/mc_state.h src/mc/mc_state.cpp src/mc/mc_visited.cpp - src/mc/mc_memory_map.h - src/mc/memory_map.cpp src/mc/mc_client.cpp src/mc/mc_client_api.cpp src/mc/mc_client.h