Logo AND Algorithmique Numérique Distribuée

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