Logo AND Algorithmique Numérique Distribuée

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