Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] Don't leave model-checked processes around
[simgrid.git] / src / mc / DwarfExpression.hpp
1 /* Copyright (c) 2015. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #ifndef SIMGRID_MC_DWARF_EXPRESSION_HPP
8 #define SIMGRID_MC_DWARF_EXPRESSION_HPP
9
10 #include <cstdint>
11 #include <cstdlib>
12 #include <stdexcept>
13
14 #include "src/mc/AddressSpace.hpp"
15
16 /** @file DwarfExession.hpp
17  *
18  *  Evaluation of DWARF location expressions
19  */
20
21 namespace simgrid {
22 namespace dwarf {
23
24 /** A DWARF expression
25  *
26  *  DWARF defines a simple stack-based VM for evaluating expressions
27  *  (such as locations of variables, etc.): A DWARF expressions is
28  *  just a sequence of dwarf instructions. We currently directly use
29  *  `Dwarf_Op` from `dwarf.h` for dwarf instructions.
30  */
31 typedef std::vector<Dwarf_Op> DwarfExpression;
32
33 /** Context of evaluation of a DWARF expression
34  *
35  *  Some DWARF instructions need to read the CPU registers,
36  *  the process memory, etc. All those informations are gathered in
37  *  the evaluation context.
38  */
39 struct ExpressionContext {
40   ExpressionContext() :
41     cursor(nullptr), frame_base(nullptr), address_space(nullptr),
42     object_info(nullptr), process_index(simgrid::mc::ProcessIndexMissing) {}
43   /** CPU state (registers) */
44   unw_cursor_t* cursor;
45   void* frame_base;
46   /** Address space used to read memory */
47   simgrid::mc::AddressSpace* address_space;
48   simgrid::mc::ObjectInformation* object_info;
49   int process_index;
50 };
51
52 /** When an error happens in the execution of a DWARF expression */
53 class evaluation_error : std::runtime_error {
54 public:
55   evaluation_error(const char* what): std::runtime_error(what) {}
56   ~evaluation_error() noexcept(true);
57 };
58
59 /** A stack for evaluating a DWARF expression
60  *
61  *  DWARF expressions work by manipulating a stack of integer values.
62  */
63 class ExpressionStack {
64 public:
65   typedef std::uintptr_t value_type;
66   static const std::size_t max_size = 64;
67 private:
68   uintptr_t stack_[max_size];
69   size_t size_;
70 public:
71   ExpressionStack() : size_(0) {}
72
73   // Access:
74   std::size_t size() const { return size_; }
75   bool empty()       const { return size_ == 0; }
76   void clear()             { size_ = 0; }
77   uintptr_t&       operator[](int i)       { return stack_[i]; }
78   uintptr_t const& operator[](int i) const { return stack_[i]; }
79
80   /** Top of the stack */
81   value_type& top()
82   {
83     if (size_ == 0)
84       throw evaluation_error("Empty stack");
85     return stack_[size_ - 1];
86   }
87
88   /** Access the i-th element from the top of the stack */
89   value_type& top(unsigned i)
90   {
91     if (size_ < i)
92       throw evaluation_error("Invalid element");
93     return stack_[size_ - 1 - i];
94   }
95
96   /** Push a value on the top of the stack */
97   void push(value_type value)
98   {
99     if (size_ == max_size)
100       throw evaluation_error("Dwarf stack overflow");
101     stack_[size_++] = value;
102   }
103
104   /* Pop a value from the top of the stack */
105   value_type pop()
106   {
107     if (size_ == 0)
108       throw evaluation_error("Stack underflow");
109     return stack_[--size_];
110   }
111
112   // These are DWARF operations (DW_OP_foo):
113
114   /* Push a copy of the top-value (DW_OP_dup) */
115   void dup() { push(top()); }
116
117   /* Swap the two top-most values */
118   void swap() { std::swap(top(), top(1)); }
119 };
120
121 /** Executes a DWARF expression
122  *
123  *  @param ops     DWARF expression instructions
124  *  @param n       number of instructions
125  *  @param context evaluation context (registers, memory, etc.)
126  *  @param stack   DWARf stack where the operations are executed
127  */
128 void execute(const Dwarf_Op* ops, std::size_t n,
129   ExpressionContext const& context, ExpressionStack& stack);
130
131 /** Executes/evaluates a DWARF expression
132  *
133  *  @param expression DWARF expression to execute
134  *  @param context    evaluation context (registers, memory, etc.)
135  *  @param stack      DWARf stack where the operations are executed
136  */
137 inline
138 void execute(simgrid::dwarf::DwarfExpression const& expression,
139   ExpressionContext const& context, ExpressionStack& stack)
140 {
141   execute(expression.data(), expression.size(), context, stack);
142 }
143
144 }
145 }
146
147 #endif