From: Martin Quinson Date: Mon, 22 Feb 2016 13:40:28 +0000 (+0100) Subject: Merge branch 'master' of scm.gforge.inria.fr:/gitroot/simgrid/simgrid X-Git-Tag: v3_13~755 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/41c54c2772412935a5c8fc9f2d09e623c0383ae7?hp=dd3b2144ace8296855c0b65efd79e325a57672f8 Merge branch 'master' of scm.gforge.inria.fr:/gitroot/simgrid/simgrid --- diff --git a/src/mc/AddressSpace.hpp b/src/mc/AddressSpace.hpp index d0c92b51e9..7c75d44bcd 100644 --- a/src/mc/AddressSpace.hpp +++ b/src/mc/AddressSpace.hpp @@ -21,7 +21,12 @@ namespace mc { /** Pointer to a remote address-space (process, snapshot) * * With this we can clearly identify the expected type of an address in the - * remote process whild avoiding to use native local pointers. + * remote process while avoiding to use native local pointers. + * + * Some operators (+/-) assume use the size of the underlying element. This + * only works if the target applications is using the same target: it won't + * work for example, when inspecting a 32 bit application from a 64 bit + * model-checker. */ template class remote_ptr { std::uint64_t address_; @@ -30,6 +35,7 @@ public: remote_ptr(std::uint64_t address) : address_(address) {} remote_ptr(T* address) : address_((std::uintptr_t)address) {} std::uint64_t address() const { return address_; } + operator bool() const { return address_; @@ -126,31 +132,100 @@ const int ProcessIndexDisabled = -2; */ const int ProcessIndexAny = 0; +/** Options for read operations + * + * This is a set of flags managed with bitwise operators. Only the + * meaningful operations are defined: addition, conversions to/from + * integers are not allowed. + */ +class ReadOptions { + std::uint32_t value_; + constexpr explicit ReadOptions(std::uint32_t value) : value_(value) {} +public: + constexpr ReadOptions() : value_(0) {} + + constexpr operator bool() const { return value_ != 0; } + constexpr bool operator!() const { return value_ == 0; } + + constexpr ReadOptions operator|(ReadOptions const& that) const + { + return ReadOptions(value_ | that.value_); + } + constexpr ReadOptions operator&(ReadOptions const& that) const + { + return ReadOptions(value_ & that.value_); + } + constexpr ReadOptions operator^(ReadOptions const& that) const + { + return ReadOptions(value_ ^ that.value_); + } + constexpr ReadOptions operator~() const + { + return ReadOptions(~value_); + } + + ReadOptions& operator|=(ReadOptions const& that) + { + value_ |= that.value_; + return *this; + } + ReadOptions& operator&=(ReadOptions const& that) + { + value_ &= that.value_; + return *this; + } + ReadOptions& operator^=(ReadOptions const& that) + { + value_ &= that.value_; + return *this; + } + + /** Copy the data to the given buffer */ + static constexpr ReadOptions none() { return ReadOptions(0); } + + /** Allows to return a pointer to another buffer where the data is + * available instead of copying the data into the buffer + */ + static constexpr ReadOptions lazy() { return ReadOptions(1); } +}; + +/** A given state of a given process (abstract base class) + * + * Currently, this might either be: + * + * * the current state of an existing process; + * + * * a snapshot. + */ class AddressSpace { private: Process* process_; public: - enum ReadMode { - Normal, - /** Allows the `read_bytes` to return a pointer to another buffer - * where the data ins available instead of copying the data into the buffer - */ - Lazy - }; AddressSpace(Process* process) : process_(process) {} virtual ~AddressSpace(); simgrid::mc::Process* process() const { return process_; } + + /** Read data from the address space + * + * @param buffer target buffer for the data + * @param size number of bytes + * @param address remote source address of the data + * @param process_index which process (used for SMPI privatization) + * @param options + */ virtual const void* read_bytes(void* buffer, std::size_t size, remote_ptr address, int process_index = ProcessIndexAny, - ReadMode mode = Normal) const = 0; + ReadOptions options = ReadOptions::none()) const = 0; + /** Read a given data structure from the address space */ template inline void read(T *buffer, remote_ptr ptr, int process_index = ProcessIndexAny) { this->read_bytes(buffer, sizeof(T), ptr, process_index); } + /** Read a given data structure from the address space */ template inline T read(remote_ptr ptr, int process_index = ProcessIndexMissing) { diff --git a/src/mc/DwarfExpression.cpp b/src/mc/DwarfExpression.cpp index ecedcb2da5..6c90f3184a 100644 --- a/src/mc/DwarfExpression.cpp +++ b/src/mc/DwarfExpression.cpp @@ -70,11 +70,12 @@ void execute( case DW_OP_breg29: case DW_OP_breg30: case DW_OP_breg31:{ + // Push register + constant: int register_id = simgrid::dwarf::dwarf_register_to_libunwind( op->atom - DW_OP_breg0); unw_word_t res; if (!context.cursor) - throw evaluation_error("Missin stack context"); + throw evaluation_error("Missing stack context"); unw_get_reg(context.cursor, register_id, &res); stack.push(res + op->number); break; @@ -117,7 +118,6 @@ void execute( // ***** Constants: // Short constant literals: - // DW_OP_lit15 pushed the 15 on the stack. case DW_OP_lit0: case DW_OP_lit1: case DW_OP_lit2: @@ -150,6 +150,7 @@ void execute( case DW_OP_lit29: case DW_OP_lit30: case DW_OP_lit31: + // Push a literal/constant on the stack: stack.push(atom - DW_OP_lit0); break; @@ -191,9 +192,8 @@ void execute( stack.pop(); break; - // Swap the two top-most value of the stack: case DW_OP_swap: - std::swap(stack.top(), stack.top(1)); + stack.swap(); break; // Duplicate the value under the top of the stack: diff --git a/src/mc/DwarfExpression.hpp b/src/mc/DwarfExpression.hpp index aa6d888cd6..fda5c6aad6 100644 --- a/src/mc/DwarfExpression.hpp +++ b/src/mc/DwarfExpression.hpp @@ -8,34 +8,58 @@ #define SIMGRID_MC_DWARF_EXPRESSION_HPP #include - +#include #include #include "src/mc/AddressSpace.hpp" +/** @file DwarfExession.hpp + * + * Evaluation of DWARF location expressions + */ + namespace simgrid { namespace dwarf { -class evaluation_error : std::runtime_error { -public: - evaluation_error(const char* what): std::runtime_error(what) {} - ~evaluation_error() noexcept(true); -}; +/** A DWARF expression + * + * DWARF defines a simple stack-based VM for evaluating expressions + * (such as locations of variables, etc.): A DWARF expressions is + * just a sequence of dwarf instructions. We currently directly use + * `Dwarf_Op` from `dwarf.h` for dwarf instructions. + */ +typedef std::vector DwarfExpression; +/** Context of evaluation of a DWARF expression + * + * Some DWARF instructions need to read the CPU registers, + * the process memory, etc. All those informations are gathered in + * the evaluation context. + */ struct ExpressionContext { ExpressionContext() : cursor(nullptr), frame_base(nullptr), address_space(nullptr), object_info(nullptr), process_index(simgrid::mc::ProcessIndexMissing) {} - + /** CPU state (registers) */ unw_cursor_t* cursor; void* frame_base; + /** Address space used to read memory */ simgrid::mc::AddressSpace* address_space; simgrid::mc::ObjectInformation* object_info; int process_index; }; -typedef std::vector DwarfExpression; +/** When an error happens in the execution of a DWARF expression */ +class evaluation_error : std::runtime_error { +public: + evaluation_error(const char* what): std::runtime_error(what) {} + ~evaluation_error() noexcept(true); +}; +/** A stack for evaluating a DWARF expression + * + * DWARF expressions work by manipulating a stack of integer values. + */ class ExpressionStack { public: typedef std::uintptr_t value_type; @@ -52,12 +76,16 @@ public: void clear() { size_ = 0; } uintptr_t& operator[](int i) { return stack_[i]; } uintptr_t const& operator[](int i) const { return stack_[i]; } + + /** Top of the stack */ value_type& top() { if (size_ == 0) throw evaluation_error("Empty stack"); return stack_[size_ - 1]; } + + /** Access the i-th element from the top of the stack */ value_type& top(unsigned i) { if (size_ < i) @@ -65,13 +93,15 @@ public: return stack_[size_ - 1 - i]; } - // Push/pop: + /** Push a value on the top of the stack */ void push(value_type value) { if (size_ == max_size) throw evaluation_error("Dwarf stack overflow"); stack_[size_++] = value; } + + /* Pop a value from the top of the stack */ value_type pop() { if (size_ == 0) @@ -79,13 +109,31 @@ public: return stack_[--size_]; } - // Other operations: + // These are DWARF operations (DW_OP_foo): + + /* Push a copy of the top-value (DW_OP_dup) */ void dup() { push(top()); } + + /* Swap the two top-most values */ + void swap() { std::swap(top(), top(1)); } }; +/** Executes a DWARF expression + * + * @param ops DWARF expression instructions + * @param n number of instructions + * @param context evaluation context (registers, memory, etc.) + * @param stack DWARf stack where the operations are executed + */ void execute(const Dwarf_Op* ops, std::size_t n, ExpressionContext const& context, ExpressionStack& stack); +/** Executes/evaluates a DWARF expression + * + * @param expression DWARF expression to execute + * @param context evaluation context (registers, memory, etc.) + * @param stack DWARf stack where the operations are executed + */ inline void execute(simgrid::dwarf::DwarfExpression const& expression, ExpressionContext const& context, ExpressionStack& stack) diff --git a/src/mc/Process.cpp b/src/mc/Process.cpp index d7e12bf060..2e6d79297c 100644 --- a/src/mc/Process.cpp +++ b/src/mc/Process.cpp @@ -506,7 +506,7 @@ char* Process::read_string(remote_ptr address) const const void *Process::read_bytes(void* buffer, std::size_t size, remote_ptr address, int process_index, - AddressSpace::ReadMode mode) const + ReadOptions options) const { if (process_index != simgrid::mc::ProcessIndexDisabled) { std::shared_ptr const& info = diff --git a/src/mc/Process.hpp b/src/mc/Process.hpp index 2f51240fcf..8780e3cc5a 100644 --- a/src/mc/Process.hpp +++ b/src/mc/Process.hpp @@ -75,7 +75,7 @@ public: // Read memory: const void* read_bytes(void* buffer, std::size_t size, remote_ptr address, int process_index = ProcessIndexAny, - ReadMode mode = Normal) const override; + ReadOptions options = ReadOptions::none()) const override; void read_variable(const char* name, void* target, size_t size) const; template T read_variable(const char *name) const diff --git a/src/mc/mc_compare.cpp b/src/mc/mc_compare.cpp index daf84c8108..dd6dd27c39 100644 --- a/src/mc/mc_compare.cpp +++ b/src/mc/mc_compare.cpp @@ -440,11 +440,11 @@ int snapshot_compare(void *state1, void *state2) xbt_mheap_t heap1 = (xbt_mheap_t)s1->read_bytes( alloca(sizeof(struct mdesc)), sizeof(struct mdesc), remote(process->heap_address), - simgrid::mc::ProcessIndexMissing, simgrid::mc::AddressSpace::Lazy); + simgrid::mc::ProcessIndexMissing, simgrid::mc::ReadOptions::lazy()); xbt_mheap_t heap2 = (xbt_mheap_t)s2->read_bytes( alloca(sizeof(struct mdesc)), sizeof(struct mdesc), remote(process->heap_address), - simgrid::mc::ProcessIndexMissing, simgrid::mc::AddressSpace::Lazy); + simgrid::mc::ProcessIndexMissing, simgrid::mc::ReadOptions::lazy()); res_init = init_heap_information(heap1, heap2, &s1->to_ignore, &s2->to_ignore); if (res_init == -1) { #ifdef MC_DEBUG @@ -520,7 +520,8 @@ int snapshot_compare(void *state1, void *state2) /* Compare global variables */ is_diff = - compare_global_variables(region1->object_info( ), simgrid::mc::AddressSpace::Normal, + compare_global_variables(region1->object_info(), + simgrid::mc::ProcessIndexDisabled, region1, region2, s1, s2); diff --git a/src/mc/mc_snapshot.cpp b/src/mc/mc_snapshot.cpp index a1ea070637..ec1bd479ba 100644 --- a/src/mc/mc_snapshot.cpp +++ b/src/mc/mc_snapshot.cpp @@ -171,12 +171,12 @@ Snapshot::~Snapshot() const void* Snapshot::read_bytes(void* buffer, std::size_t size, remote_ptr address, int process_index, - AddressSpace::ReadMode mode) const + ReadOptions options) const { mc_mem_region_t region = mc_get_snapshot_region((void*)address.address(), this, process_index); if (region) { const void* res = MC_region_read(region, buffer, (void*)address.address(), size); - if (buffer == res || mode == AddressSpace::Lazy) + if (buffer == res || options & ReadOptions::lazy()) return res; else { memcpy(buffer, res, size); @@ -185,7 +185,7 @@ const void* Snapshot::read_bytes(void* buffer, std::size_t size, } else return this->process()->read_bytes( - buffer, size, address, process_index, mode); + buffer, size, address, process_index, options); } } diff --git a/src/mc/mc_snapshot.h b/src/mc/mc_snapshot.h index 5c638f6f81..8960b450a2 100644 --- a/src/mc/mc_snapshot.h +++ b/src/mc/mc_snapshot.h @@ -146,7 +146,7 @@ public: ~Snapshot(); const void* read_bytes(void* buffer, std::size_t size, remote_ptr address, int process_index = ProcessIndexAny, - ReadMode mode = Normal) const override; + ReadOptions options = ReadOptions::none()) const override; public: // To be private int num_state; std::size_t heap_bytes_used; diff --git a/src/surf/surf_routing.cpp b/src/surf/surf_routing.cpp index ef1c70a51e..3028a23b2a 100644 --- a/src/surf/surf_routing.cpp +++ b/src/surf/surf_routing.cpp @@ -78,7 +78,7 @@ namespace surf { char *route_name = bprintf("%s#%s", src->name(), dst->name()); if (bypassRoutes_->find(route_name) != bypassRoutes_->end()) { bypassedRoute = bypassRoutes_->at(route_name); - XBT_DEBUG("Found a bypass route with %ld links",bypassedRoute->size()); + XBT_DEBUG("Found a bypass route with %zu links",bypassedRoute->size()); } free(route_name); return bypassedRoute;