Logo AND Algorithmique Numérique Distribuée

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