Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[jenkins] better location for the jenkins configuration files
[simgrid.git] / src / mc / mc_dwarf_expression.cpp
1 /* Copyright (c) 2014-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 #include <cstdint>
8
9 #include <stdint.h>
10 #include <stdarg.h>
11
12 #include <dwarf.h>
13
14 #include "mc_dwarf.hpp"
15 #include "mc_private.h"
16 #include "mc_location.h"
17 #include "mc/AddressSpace.hpp"
18 #include "mc/Frame.hpp"
19 #include "mc/ObjectInformation.hpp"
20
21 using simgrid::mc::remote;
22
23 extern "C" {
24
25 static int mc_dwarf_push_value(mc_expression_state_t state, std::uint64_t value)
26 {
27   if (state->stack_size >= MC_EXPRESSION_STACK_SIZE)
28     return MC_EXPRESSION_E_STACK_OVERFLOW;
29
30   state->stack[state->stack_size++] = value;
31   return 0;
32 }
33
34 /** Convert a DWARF register into a libunwind register
35  *
36  *  DWARF and libunwind does not use the same convention for numbering the
37  *  registers on some architectures. The function makes the necessary
38  *  convertion.
39  */
40 static int mc_dwarf_register_to_libunwind(int dwarf_register)
41 {
42 #if defined(__x86_64__)
43   // It seems for this arch, DWARF and libunwind agree in the numbering:
44   return dwarf_register;
45 #elif defined(__i386__)
46   // Could't find the authoritative source of information for this.
47   // This is inspired from http://source.winehq.org/source/dlls/dbghelp/cpu_i386.c#L517.
48   switch (dwarf_register) {
49   case 0:
50     return UNW_X86_EAX;
51   case 1:
52     return UNW_X86_ECX;
53   case 2:
54     return UNW_X86_EDX;
55   case 3:
56     return UNW_X86_EBX;
57   case 4:
58     return UNW_X86_ESP;
59   case 5:
60     return UNW_X86_EBP;
61   case 6:
62     return UNW_X86_ESI;
63   case 7:
64     return UNW_X86_EDI;
65   case 8:
66     return UNW_X86_EIP;
67   case 9:
68     return UNW_X86_EFLAGS;
69   case 10:
70     return UNW_X86_CS;
71   case 11:
72     return UNW_X86_SS;
73   case 12:
74     return UNW_X86_DS;
75   case 13:
76     return UNW_X86_ES;
77   case 14:
78     return UNW_X86_FS;
79   case 15:
80     return UNW_X86_GS;
81   case 16:
82     return UNW_X86_ST0;
83   case 17:
84     return UNW_X86_ST1;
85   case 18:
86     return UNW_X86_ST2;
87   case 19:
88     return UNW_X86_ST3;
89   case 20:
90     return UNW_X86_ST4;
91   case 21:
92     return UNW_X86_ST5;
93   case 22:
94     return UNW_X86_ST6;
95   case 23:
96     return UNW_X86_ST7;
97   default:
98     xbt_die("Bad/unknown register number.");
99   }
100 #else
101 #error This architecture is not supported yet for DWARF expression evaluation.
102 #endif
103 }
104
105 int mc_dwarf_execute_expression(size_t n, const simgrid::mc::DwarfInstruction* ops,
106                                 mc_expression_state_t state)
107 {
108   for (size_t i = 0; i != n; ++i) {
109     int error = 0;
110     const simgrid::mc::DwarfInstruction *op = ops + i;
111     uint8_t atom = op->atom;
112
113     switch (atom) {
114
115       // Registers:
116
117     case DW_OP_breg0:
118     case DW_OP_breg1:
119     case DW_OP_breg2:
120     case DW_OP_breg3:
121     case DW_OP_breg4:
122     case DW_OP_breg5:
123     case DW_OP_breg6:
124     case DW_OP_breg7:
125     case DW_OP_breg8:
126     case DW_OP_breg9:
127     case DW_OP_breg10:
128     case DW_OP_breg11:
129     case DW_OP_breg12:
130     case DW_OP_breg13:
131     case DW_OP_breg14:
132     case DW_OP_breg15:
133     case DW_OP_breg16:
134     case DW_OP_breg17:
135     case DW_OP_breg18:
136     case DW_OP_breg19:
137     case DW_OP_breg20:
138     case DW_OP_breg21:
139     case DW_OP_breg22:
140     case DW_OP_breg23:
141     case DW_OP_breg24:
142     case DW_OP_breg25:
143     case DW_OP_breg26:
144     case DW_OP_breg27:
145     case DW_OP_breg28:
146     case DW_OP_breg29:
147     case DW_OP_breg30:
148     case DW_OP_breg31:{
149         int register_id =
150             mc_dwarf_register_to_libunwind(op->atom - DW_OP_breg0);
151         unw_word_t res;
152         if (!state->cursor)
153           return MC_EXPRESSION_E_MISSING_STACK_CONTEXT;
154         unw_get_reg(state->cursor, register_id, &res);
155         error = mc_dwarf_push_value(state, res + op->number);
156         break;
157       }
158
159       // Push the CFA (Canonical Frame Addresse):
160     case DW_OP_call_frame_cfa:
161       {
162         // UNW_X86_64_CFA does not return the CFA DWARF expects
163         // (it is a synonym for UNW_X86_64_RSP) so copy the cursor,
164         // unwind it once in order to find the parent SP:
165
166         if (!state->cursor)
167           return MC_EXPRESSION_E_MISSING_STACK_CONTEXT;
168
169         // Get frame:
170         unw_cursor_t cursor = *(state->cursor);
171         unw_step(&cursor);
172
173         unw_word_t res;
174         unw_get_reg(&cursor, UNW_REG_SP, &res);
175         error = mc_dwarf_push_value(state, res);
176         break;
177       }
178
179       // Frame base:
180
181     case DW_OP_fbreg:
182       {
183         if (!state->frame_base)
184           return MC_EXPRESSION_E_MISSING_FRAME_BASE;
185         uintptr_t fb = ((uintptr_t) state->frame_base) + op->number;
186         error = mc_dwarf_push_value(state, fb);
187         break;
188       }
189
190
191       // ***** Constants:
192
193       // Short constant literals:
194       // DW_OP_lit15 pushed the 15 on the stack.
195     case DW_OP_lit0:
196     case DW_OP_lit1:
197     case DW_OP_lit2:
198     case DW_OP_lit3:
199     case DW_OP_lit4:
200     case DW_OP_lit5:
201     case DW_OP_lit6:
202     case DW_OP_lit7:
203     case DW_OP_lit8:
204     case DW_OP_lit9:
205     case DW_OP_lit10:
206     case DW_OP_lit11:
207     case DW_OP_lit12:
208     case DW_OP_lit13:
209     case DW_OP_lit14:
210     case DW_OP_lit15:
211     case DW_OP_lit16:
212     case DW_OP_lit17:
213     case DW_OP_lit18:
214     case DW_OP_lit19:
215     case DW_OP_lit20:
216     case DW_OP_lit21:
217     case DW_OP_lit22:
218     case DW_OP_lit23:
219     case DW_OP_lit24:
220     case DW_OP_lit25:
221     case DW_OP_lit26:
222     case DW_OP_lit27:
223     case DW_OP_lit28:
224     case DW_OP_lit29:
225     case DW_OP_lit30:
226     case DW_OP_lit31:
227       error = mc_dwarf_push_value(state, atom - DW_OP_lit0);
228       break;
229
230       // Address from the base address of this ELF object.
231       // Push the address on the stack (base_address + argument).
232     case DW_OP_addr: {
233       if (!state->object_info)
234         return MC_EXPRESSION_E_NO_BASE_ADDRESS;
235       if (state->stack_size == MC_EXPRESSION_STACK_SIZE)
236         return MC_EXPRESSION_E_STACK_OVERFLOW;
237       std::uint64_t addr = (std::uint64_t) (uintptr_t)
238         state->object_info->base_address() + op->number;
239       error = mc_dwarf_push_value(state, addr);
240       break;
241     }
242
243       // General constants:
244       // Push the constant argument on the stack.
245     case DW_OP_const1u:
246     case DW_OP_const2u:
247     case DW_OP_const4u:
248     case DW_OP_const8u:
249     case DW_OP_const1s:
250     case DW_OP_const2s:
251     case DW_OP_const4s:
252     case DW_OP_const8s:
253     case DW_OP_constu:
254     case DW_OP_consts:
255       if (state->stack_size == MC_EXPRESSION_STACK_SIZE)
256         return MC_EXPRESSION_E_STACK_OVERFLOW;
257       error = mc_dwarf_push_value(state, op->number);
258       break;
259
260       // ***** Stack manipulation:
261
262       // Push another copy/duplicate the value at the top of the stack:
263     case DW_OP_dup:
264       if (state->stack_size == 0)
265         return MC_EXPRESSION_E_STACK_UNDERFLOW;
266       else
267         error = mc_dwarf_push_value(state, state->stack[state->stack_size - 1]);
268       break;
269
270       // Pop/drop the top of the stack:
271     case DW_OP_drop:
272       if (state->stack_size == 0)
273         return MC_EXPRESSION_E_STACK_UNDERFLOW;
274       else
275         state->stack_size--;
276       break;
277
278       // Swap the two top-most value of the stack:
279     case DW_OP_swap:
280       if (state->stack_size < 2)
281         return MC_EXPRESSION_E_STACK_UNDERFLOW;
282       {
283         uintptr_t temp = state->stack[state->stack_size - 2];
284         state->stack[state->stack_size - 2] =
285             state->stack[state->stack_size - 1];
286         state->stack[state->stack_size - 1] = temp;
287       }
288       break;
289
290       // Duplicate the value under the top of the stack:
291     case DW_OP_over:
292       if (state->stack_size < 2)
293         return MC_EXPRESSION_E_STACK_UNDERFLOW;
294       error = mc_dwarf_push_value(state, state->stack[state->stack_size - 2]);
295       break;
296
297       // ***** Operations:
298       // Those usually take the top of the stack and the next value as argument
299       // and replace the top of the stack with the computed value
300       // (stack.top() += stack.before_top()).
301
302     case DW_OP_plus:
303       if (state->stack_size < 2)
304         return MC_EXPRESSION_E_STACK_UNDERFLOW;
305       {
306         uintptr_t result =
307             state->stack[state->stack_size - 2] +
308             state->stack[state->stack_size - 1];
309         state->stack[state->stack_size - 2] = result;
310         state->stack_size--;
311       }
312       break;
313
314     case DW_OP_mul:
315       if (state->stack_size < 2)
316         return MC_EXPRESSION_E_STACK_UNDERFLOW;
317       {
318         uintptr_t result =
319             state->stack[state->stack_size - 2] -
320             state->stack[state->stack_size - 1];
321         state->stack[state->stack_size - 2] = result;
322         state->stack_size--;
323       }
324       break;
325
326     case DW_OP_plus_uconst:
327       if (state->stack_size == 0)
328         return MC_EXPRESSION_E_STACK_UNDERFLOW;
329       state->stack[state->stack_size - 1] += op->number;
330       break;
331
332     case DW_OP_not:
333       if (state->stack_size == 0)
334         return MC_EXPRESSION_E_STACK_UNDERFLOW;
335       state->stack[state->stack_size - 1] =
336           ~state->stack[state->stack_size - 1];
337       break;
338
339     case DW_OP_neg:
340       if (state->stack_size == 0)
341         return MC_EXPRESSION_E_STACK_UNDERFLOW;
342       {
343         intptr_t value = state->stack[state->stack_size - 1];
344         if (value < 0)
345           value = -value;
346         state->stack[state->stack_size - 1] = value;
347       }
348       break;
349
350     case DW_OP_minus:
351       if (state->stack_size < 2)
352         return MC_EXPRESSION_E_STACK_UNDERFLOW;
353       {
354         uintptr_t result =
355             state->stack[state->stack_size - 2] -
356             state->stack[state->stack_size - 1];
357         state->stack[state->stack_size - 2] = result;
358         state->stack_size--;
359       }
360       break;
361
362     case DW_OP_and:
363       if (state->stack_size < 2)
364         return MC_EXPRESSION_E_STACK_UNDERFLOW;
365       {
366         uintptr_t result =
367             state->stack[state->stack_size -
368                          2] & state->stack[state->stack_size - 1];
369         state->stack[state->stack_size - 2] = result;
370         state->stack_size--;
371       }
372       break;
373
374     case DW_OP_or:
375       if (state->stack_size < 2)
376         return MC_EXPRESSION_E_STACK_UNDERFLOW;
377       {
378         uintptr_t result =
379             state->stack[state->stack_size -
380                          2] | state->stack[state->stack_size - 1];
381         state->stack[state->stack_size - 2] = result;
382         state->stack_size--;
383       }
384       break;
385
386     case DW_OP_xor:
387       if (state->stack_size < 2)
388         return MC_EXPRESSION_E_STACK_UNDERFLOW;
389       {
390         uintptr_t result =
391             state->stack[state->stack_size -
392                          2] ^ state->stack[state->stack_size - 1];
393         state->stack[state->stack_size - 2] = result;
394         state->stack_size--;
395       }
396       break;
397
398     case DW_OP_nop:
399       break;
400
401       // ***** Deference (memory fetch)
402
403     case DW_OP_deref_size:
404       return MC_EXPRESSION_E_UNSUPPORTED_OPERATION;
405
406     case DW_OP_deref:
407       if (state->stack_size == 0)
408         return MC_EXPRESSION_E_STACK_UNDERFLOW;
409       {
410         // Computed address:
411         uintptr_t address = (uintptr_t) state->stack[state->stack_size - 1];
412         if (!state->address_space)
413           xbt_die("Missing address space");
414         state->address_space->read_bytes(
415           &state->stack[state->stack_size - 1], sizeof(uintptr_t),
416           remote(address), state->process_index);
417       }
418       break;
419
420       // Not handled:
421     default:
422       return MC_EXPRESSION_E_UNSUPPORTED_OPERATION;
423     }
424
425     if (error)
426       return error;
427   }
428   return 0;
429 }
430
431 // ***** Location
432
433 /** \brief Resolve a location expression
434  *  \deprecated Use mc_dwarf_resolve_expression
435  */
436 void mc_dwarf_resolve_location(mc_location_t location,
437                                simgrid::mc::DwarfExpression* expression,
438                                simgrid::mc::ObjectInformation* object_info,
439                                unw_cursor_t * c,
440                                void *frame_pointer_address,
441                                simgrid::mc::AddressSpace* address_space, int process_index)
442 {
443   s_mc_expression_state_t state;
444   memset(&state, 0, sizeof(s_mc_expression_state_t));
445   state.frame_base = frame_pointer_address;
446   state.cursor = c;
447   state.address_space = address_space;
448   state.object_info = object_info;
449   state.process_index = process_index;
450
451   if (expression->size() >= 1
452       && (*expression)[0].atom >=DW_OP_reg0
453       && (*expression)[0].atom <= DW_OP_reg31) {
454     int dwarf_register = (*expression)[0].atom - DW_OP_reg0;
455     xbt_assert(c,
456       "Missing frame context for register operation DW_OP_reg%i",
457       dwarf_register);
458     location->memory_location = NULL;
459     location->cursor = c;
460     location->register_id = mc_dwarf_register_to_libunwind(dwarf_register);
461     return;
462   }
463
464   if (mc_dwarf_execute_expression(
465       expression->size(), expression->data(), &state))
466     xbt_die("Error evaluating DWARF expression");
467   if (state.stack_size == 0)
468     xbt_die("No value on the stack");
469   else {
470     location->memory_location = (void*) state.stack[state.stack_size - 1];
471     location->cursor = NULL;
472     location->register_id = 0;
473   }
474 }
475
476 // TODO, move this in a method of LocationList
477 static simgrid::mc::DwarfExpression* mc_find_expression(
478     simgrid::mc::LocationList* locations, unw_word_t ip)
479 {
480   for (simgrid::mc::LocationListEntry& entry : *locations)
481     if (entry.valid_for_ip(ip))
482       return &entry.expression;
483   return nullptr;
484 }
485
486 void mc_dwarf_resolve_locations(mc_location_t location,
487                                 simgrid::mc::LocationList* locations,
488                                 simgrid::mc::ObjectInformation* object_info,
489                                 unw_cursor_t * c,
490                                 void *frame_pointer_address,
491                                 simgrid::mc::AddressSpace* address_space,
492                                 int process_index)
493 {
494
495   unw_word_t ip = 0;
496   if (c) {
497     if (unw_get_reg(c, UNW_REG_IP, &ip))
498       xbt_die("Could not resolve IP");
499   }
500
501   simgrid::mc::DwarfExpression* expression = mc_find_expression(locations, ip);
502   if (expression) {
503     mc_dwarf_resolve_location(location,
504                               expression, object_info, c,
505                               frame_pointer_address, address_space, process_index);
506   } else {
507     xbt_die("Could not resolve location");
508   }
509 }
510
511 /** \brief Find the frame base of a given frame
512  *
513  *  \param frame
514  *  \param unw_cursor
515  */
516 void *mc_find_frame_base(simgrid::mc::Frame* frame, simgrid::mc::ObjectInformation* object_info,
517                          unw_cursor_t * unw_cursor)
518 {
519   s_mc_location_t location;
520   mc_dwarf_resolve_locations(&location,
521                              &frame->frame_base, object_info,
522                              unw_cursor, NULL, NULL, -1);
523   switch(mc_get_location_type(&location)) {
524   case MC_LOCATION_TYPE_ADDRESS:
525     return location.memory_location;
526
527   case MC_LOCATION_TYPE_REGISTER: {
528       // This is a special case.
529       // The register if not the location of the frame base
530       // (a frame base cannot be located in a register)
531       // Instead, DWARF defines this to mean that the register
532       // contains the address of the frame base.
533       unw_word_t word;
534       unw_get_reg(location.cursor, location.register_id, &word);
535       return (void*) word;
536     }
537
538   default:
539     xbt_die("Cannot handle non-address frame base");
540     return NULL; // Unreachable
541   }
542 }
543
544 }