Logo AND Algorithmique Numérique Distribuée

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