Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of scm.gforge.inria.fr:/gitroot/simgrid/simgrid
authorMartin Quinson <martin.quinson@loria.fr>
Mon, 22 Feb 2016 13:40:28 +0000 (14:40 +0100)
committerMartin Quinson <martin.quinson@loria.fr>
Mon, 22 Feb 2016 13:40:28 +0000 (14:40 +0100)
src/mc/AddressSpace.hpp
src/mc/DwarfExpression.cpp
src/mc/DwarfExpression.hpp
src/mc/Process.cpp
src/mc/Process.hpp
src/mc/mc_compare.cpp
src/mc/mc_snapshot.cpp
src/mc/mc_snapshot.h
src/surf/surf_routing.cpp

index d0c92b5..7c75d44 100644 (file)
@@ -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 T> 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<void> 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<class T> inline
   void read(T *buffer, remote_ptr<T> ptr, int process_index = ProcessIndexAny)
   {
     this->read_bytes(buffer, sizeof(T), ptr, process_index);
   }
 
+  /** Read a given data structure from the address space */
   template<class T> inline
   T read(remote_ptr<T> ptr, int process_index = ProcessIndexMissing)
   {
index ecedcb2..6c90f31 100644 (file)
@@ -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:
index aa6d888..fda5c6a 100644 (file)
@@ -8,34 +8,58 @@
 #define SIMGRID_MC_DWARF_EXPRESSION_HPP
 
 #include <cstdint>
-
+#include <cstdlib>
 #include <stdexcept>
 
 #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<Dwarf_Op> 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<Dwarf_Op> 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)
index d7e12bf..2e6d792 100644 (file)
@@ -506,7 +506,7 @@ char* Process::read_string(remote_ptr<void> address) const
 
 const void *Process::read_bytes(void* buffer, std::size_t size,
   remote_ptr<void> address, int process_index,
-  AddressSpace::ReadMode mode) const
+  ReadOptions options) const
 {
   if (process_index != simgrid::mc::ProcessIndexDisabled) {
     std::shared_ptr<simgrid::mc::ObjectInformation> const& info =
index 2f51240..8780e3c 100644 (file)
@@ -75,7 +75,7 @@ public:
   // Read memory:
   const void* read_bytes(void* buffer, std::size_t size,
     remote_ptr<void> 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<class T>
   T read_variable(const char *name) const
index daf84c8..dd6dd27 100644 (file)
@@ -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);
 
index a1ea070..ec1bd47 100644 (file)
@@ -171,12 +171,12 @@ Snapshot::~Snapshot()
 
 const void* Snapshot::read_bytes(void* buffer, std::size_t size,
   remote_ptr<void> 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);
 }
 
 }
index 5c638f6..8960b45 100644 (file)
@@ -146,7 +146,7 @@ public:
   ~Snapshot();
   const void* read_bytes(void* buffer, std::size_t size,
     remote_ptr<void> 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;
index ef1c70a..3028a23 100644 (file)
@@ -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;