Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
another bunch of cleanups
[simgrid.git] / src / mc / inspect / DwarfExpression.cpp
1 /* Copyright (c) 2014-2019. The SimGrid Team. All rights reserved.          */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #include <cstddef>
7 #include <cstdint>
8
9 #include "src/mc/AddressSpace.hpp"
10 #include "src/mc/inspect/DwarfExpression.hpp"
11 #include "src/mc/inspect/Frame.hpp"
12 #include "src/mc/inspect/LocationList.hpp"
13 #include "src/mc/inspect/ObjectInformation.hpp"
14 #include "src/mc/inspect/mc_dwarf.hpp"
15 #include "src/mc/mc_private.hpp"
16
17 using simgrid::mc::remote;
18
19 namespace simgrid {
20 namespace dwarf {
21
22 void execute(const Dwarf_Op* ops, std::size_t n, const ExpressionContext& context, ExpressionStack& stack)
23 {
24   for (size_t i = 0; i != n; ++i) {
25     const Dwarf_Op* op = ops + i;
26     std::uint8_t atom  = op->atom;
27     intptr_t first;
28     intptr_t second;
29
30     switch (atom) {
31         // Registers:
32       case DW_OP_breg0:
33       case DW_OP_breg1:
34       case DW_OP_breg2:
35       case DW_OP_breg3:
36       case DW_OP_breg4:
37       case DW_OP_breg5:
38       case DW_OP_breg6:
39       case DW_OP_breg7:
40       case DW_OP_breg8:
41       case DW_OP_breg9:
42       case DW_OP_breg10:
43       case DW_OP_breg11:
44       case DW_OP_breg12:
45       case DW_OP_breg13:
46       case DW_OP_breg14:
47       case DW_OP_breg15:
48       case DW_OP_breg16:
49       case DW_OP_breg17:
50       case DW_OP_breg18:
51       case DW_OP_breg19:
52       case DW_OP_breg20:
53       case DW_OP_breg21:
54       case DW_OP_breg22:
55       case DW_OP_breg23:
56       case DW_OP_breg24:
57       case DW_OP_breg25:
58       case DW_OP_breg26:
59       case DW_OP_breg27:
60       case DW_OP_breg28:
61       case DW_OP_breg29:
62       case DW_OP_breg30:
63       case DW_OP_breg31: {
64         // Push register + constant:
65         int register_id = simgrid::dwarf::dwarf_register_to_libunwind(op->atom - DW_OP_breg0);
66         unw_word_t res;
67         if (not context.cursor)
68           throw evaluation_error("Missing stack context");
69         unw_get_reg(context.cursor, register_id, &res);
70         stack.push(res + op->number);
71         break;
72       }
73
74         // Push the CFA (Canonical Frame Address):
75       case DW_OP_call_frame_cfa: {
76         /* See 6.4 of DWARF4 (http://dwarfstd.org/doc/DWARF4.pdf#page=140):
77          *
78          * > Typically, the CFA is defined to be the value of the stack
79          * > pointer at the call site in the previous frame (which may be
80          * > different from its value on entry to the current frame).
81          *
82          * We need to unwind the frame in order to get the SP of the parent
83          * frame.
84          *
85          * Warning: the CFA returned by libunwind (UNW_X86_64_RSP, etc.)
86          * is the SP of the *current* frame. */
87
88         if (not context.cursor)
89           throw evaluation_error("Missint cursor");
90
91         // Get frame:
92         unw_cursor_t cursor = *(context.cursor);
93         unw_step(&cursor);
94
95         unw_word_t res;
96         unw_get_reg(&cursor, UNW_REG_SP, &res);
97         stack.push(res);
98         break;
99       }
100
101         // Frame base:
102
103       case DW_OP_fbreg:
104         stack.push((std::uintptr_t)context.frame_base + op->number);
105         break;
106
107         // ***** Constants:
108
109         // Short constant literals:
110       case DW_OP_lit0:
111       case DW_OP_lit1:
112       case DW_OP_lit2:
113       case DW_OP_lit3:
114       case DW_OP_lit4:
115       case DW_OP_lit5:
116       case DW_OP_lit6:
117       case DW_OP_lit7:
118       case DW_OP_lit8:
119       case DW_OP_lit9:
120       case DW_OP_lit10:
121       case DW_OP_lit11:
122       case DW_OP_lit12:
123       case DW_OP_lit13:
124       case DW_OP_lit14:
125       case DW_OP_lit15:
126       case DW_OP_lit16:
127       case DW_OP_lit17:
128       case DW_OP_lit18:
129       case DW_OP_lit19:
130       case DW_OP_lit20:
131       case DW_OP_lit21:
132       case DW_OP_lit22:
133       case DW_OP_lit23:
134       case DW_OP_lit24:
135       case DW_OP_lit25:
136       case DW_OP_lit26:
137       case DW_OP_lit27:
138       case DW_OP_lit28:
139       case DW_OP_lit29:
140       case DW_OP_lit30:
141       case DW_OP_lit31:
142         // Push a literal/constant on the stack:
143         stack.push(atom - DW_OP_lit0);
144         break;
145
146         // Address from the base address of this ELF object.
147         // Push the address on the stack (base_address + argument).
148       case DW_OP_addr: {
149         if (not context.object_info)
150           throw evaluation_error("No base address");
151         Dwarf_Off addr = (Dwarf_Off)(std::uintptr_t)context.object_info->base_address() + op->number;
152         stack.push(addr);
153         break;
154       }
155
156         // General constants:
157         // Push the constant argument on the stack.
158       case DW_OP_const1u:
159       case DW_OP_const2u:
160       case DW_OP_const4u:
161       case DW_OP_const8u:
162       case DW_OP_const1s:
163       case DW_OP_const2s:
164       case DW_OP_const4s:
165       case DW_OP_const8s:
166       case DW_OP_constu:
167       case DW_OP_consts:
168         stack.push(op->number);
169         break;
170
171         // ***** Stack manipulation:
172
173         // Push another copy/duplicate the value at the top of the stack:
174       case DW_OP_dup:
175         stack.dup();
176         break;
177
178         // Pop/drop the top of the stack:
179       case DW_OP_drop:
180         stack.pop();
181         break;
182
183       case DW_OP_swap:
184         stack.swap();
185         break;
186
187         // Duplicate the value under the top of the stack:
188       case DW_OP_over:
189         stack.push(stack.top(1));
190         break;
191
192         // ***** Operations:
193         // Those usually take the top of the stack and the next value as argument
194         // and replace the top of the stack with the computed value
195         // (stack.top() += stack.before_top()).
196
197       case DW_OP_plus:
198         first  = stack.pop();
199         second = stack.pop();
200         stack.push(first + second);
201         break;
202
203       case DW_OP_mul:
204         first  = stack.pop();
205         second = stack.pop();
206         stack.push(first * second);
207         break;
208
209       case DW_OP_plus_uconst:
210         stack.top() += op->number;
211         break;
212
213       case DW_OP_not:
214         stack.top() = ~stack.top();
215         break;
216
217       case DW_OP_neg:
218         stack.top() = -(intptr_t)stack.top();
219         break;
220
221       case DW_OP_minus:
222         first  = stack.pop();
223         second = stack.pop();
224         stack.push(second - first);
225         break;
226
227       case DW_OP_and:
228         first  = stack.pop();
229         second = stack.pop();
230         stack.push(first & second);
231         break;
232
233       case DW_OP_or:
234         first  = stack.pop();
235         second = stack.pop();
236         stack.push(first | second);
237         break;
238
239       case DW_OP_xor:
240         first  = stack.pop();
241         second = stack.pop();
242         stack.push(first ^ second);
243         break;
244
245       case DW_OP_nop:
246         break;
247
248         // ***** Deference (memory fetch)
249
250       case DW_OP_deref_size:
251         throw evaluation_error("Unsupported operation");
252
253       case DW_OP_deref:
254         // Computed address:
255         if (not context.address_space)
256           throw evaluation_error("Missing address space");
257         context.address_space->read_bytes(&stack.top(), sizeof(uintptr_t), remote(stack.top()));
258         break;
259
260         // Not handled:
261       default:
262         throw evaluation_error("Unsupported operation");
263     }
264   }
265 }
266
267 } // namespace dwarf
268 } // namespace simgrid